/**
 * \file
 * \brief cert definition tests
 *
 * \copyright (c) 2015-2020 Microchip Technology Inc. and its subsidiaries.
 *
 * \page License
 *
 * Subject to your compliance with these terms, you may use Microchip software
 * and any derivatives exclusively with Microchip products. It is your
 * responsibility to comply with third party license terms applicable to your
 * use of third party software (including open source software) that may
 * accompany Microchip software.
 *
 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
 * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
 * PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
 * SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
 * OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
 * MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
 * FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
 * LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
 * THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
 * THIS SOFTWARE.
 */
#include "atca_test.h"
#ifndef DO_NOT_TEST_CERT

#include "atcacert/atcacert_def.h"
#include "test_cert_def_0_device.h"
#include "test_cert_def_1_signer.h"
#include "test_cert_def_3_device.h"
#include <string.h>

uint8_t g_cert_def_cert_template[800];
atcacert_def_t g_cert_def;

static const uint8_t g_test_public_key[64] = {
    0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF,
    0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9,
    0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C,
    0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E
};

static void useCert(const atcacert_def_t* cert_def)
{
    TEST_ASSERT(sizeof(g_cert_def_cert_template) >= cert_def->cert_template_size);
    memcpy(g_cert_def_cert_template, cert_def->cert_template, cert_def->cert_template_size);
    memcpy(&g_cert_def, cert_def, sizeof(g_cert_def));
    g_cert_def.cert_template = g_cert_def_cert_template;
}


TEST_GROUP(atcacert_get_key_id);

TEST_SETUP(atcacert_get_key_id)
{
}

TEST_TEAR_DOWN(atcacert_get_key_id)
{
}

TEST(atcacert_get_key_id, good)
{
    int ret = 0;
    static const uint8_t public_key[64] = {
        0xE0, 0xDD, 0xF9, 0x0A, 0x94, 0x5A, 0xF3, 0x91, 0x1B, 0x52, 0x49, 0xC0, 0xD9, 0x99, 0x13, 0xC1,
        0xD0, 0x73, 0xB6, 0xFC, 0xF0, 0xB1, 0x3F, 0xF3, 0xA6, 0x84, 0x5F, 0xC1, 0xF5, 0x13, 0x79, 0x28,
        0x93, 0xE9, 0x35, 0xA0, 0x95, 0x19, 0x2F, 0xD1, 0x62, 0x52, 0xD4, 0x88, 0x0C, 0xC3, 0x1D, 0x05,
        0xBF, 0x04, 0x54, 0x6F, 0x17, 0x9F, 0xDA, 0xE7, 0xBB, 0xDB, 0xC6, 0x89, 0x27, 0xD7, 0xA3, 0x69
    };
    static const uint8_t key_id_ref[20] = {
        0x77, 0x23, 0xA2, 0xC4, 0x32, 0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D,
        0xD2, 0xBE, 0x95, 0x5D
    };
    uint8_t key_id[sizeof(key_id_ref)];

    ret = atcacert_get_key_id(public_key, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(key_id_ref, key_id, sizeof(key_id));
}

TEST(atcacert_get_key_id, bad_params)
{
    int ret = 0;
    uint8_t key_id[20];

    ret = atcacert_get_key_id(NULL, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_key_id(g_test_public_key, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_key_id(NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_cert_element);

TEST_SETUP(atcacert_set_cert_element)
{
}

TEST_TEAR_DOWN(atcacert_set_cert_element)
{
}

TEST(atcacert_set_cert_element, good)
{
    int ret = 0;
    uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t cert_ref[sizeof(cert)] = { 0x00, 0x01, 0x06, 0x07, 0x08, 0x05 };
    static const uint8_t data[] = { 0x06, 0x07, 0x08 };
    atcacert_cert_loc_t cert_loc = { .offset = 2, .count = sizeof(data) };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, sizeof(cert));
}

TEST(atcacert_set_cert_element, edge)
{
    int ret = 0;
    uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t cert_ref[sizeof(cert)] = { 0x00, 0x01, 0x02, 0x06, 0x07, 0x08 };
    static const uint8_t data[] = { 0x06, 0x07, 0x08 };
    atcacert_cert_loc_t cert_loc = { .offset = 3, .count = sizeof(data) };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, sizeof(cert));
}

TEST(atcacert_set_cert_element, missing)
{
    int ret = 0;
    uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t cert_ref[sizeof(cert)] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t data[] = { 0x06, 0x07, 0x08 };
    atcacert_cert_loc_t cert_loc = { .offset = 2, .count = 0 };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, sizeof(cert));
}

TEST(atcacert_set_cert_element, unexpected_size)
{
    int ret = 0;
    uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t data[] = { 0x06, 0x07, 0x08 };
    atcacert_cert_loc_t cert_loc = { .offset = 2, .count = sizeof(data) };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data) - 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data) + 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);
}

TEST(atcacert_set_cert_element, out_of_bounds)
{
    int ret = 0;
    uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t data[] = { 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D };
    atcacert_cert_loc_t cert_loc;
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    cert_loc.offset = 2;
    cert_loc.count = sizeof(cert);
    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, cert_loc.count);
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_OUT_OF_BOUNDS, ret);

    cert_loc.offset = 0;
    cert_loc.count = sizeof(cert) + 1;
    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, cert_loc.count);
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_OUT_OF_BOUNDS, ret);
}

TEST(atcacert_set_cert_element, bad_params)
{
    int ret = 0;
    uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t data[] = { 0x06, 0x07, 0x08 };
    atcacert_cert_loc_t cert_loc = { .offset = 2, .count = sizeof(data) };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_set_cert_element(NULL, &cert_loc, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(&cert_def, NULL, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(NULL, NULL, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, NULL, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(NULL, &cert_loc, NULL, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(&cert_def, NULL, NULL, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(NULL, NULL, NULL, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(NULL, &cert_loc, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(&cert_def, NULL, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(NULL, NULL, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(&cert_def, &cert_loc, NULL, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(NULL, &cert_loc, NULL, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(&cert_def, NULL, NULL, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_element(NULL, NULL, NULL, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_cert_element);

TEST_SETUP(atcacert_get_cert_element)
{
}

TEST_TEAR_DOWN(atcacert_get_cert_element)
{
}

TEST(atcacert_get_cert_element, good)
{
    int ret = 0;
    uint8_t data[] = { 0x00, 0x00, 0x00 };
    static const uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    static const uint8_t data_ref[sizeof(data)] = { 0x02, 0x03, 0x04 };
    static const atcacert_cert_loc_t cert_loc = { .offset = 2, .count = sizeof(data) };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_get_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(data_ref, data, sizeof(data));
}

TEST(atcacert_get_cert_element, missing)
{
    int ret = 0;
    static const uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    uint8_t data[3];
    static const atcacert_cert_loc_t cert_loc = { .offset = 2, .count = 0 };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_get_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_MISSING, ret);
}

TEST(atcacert_get_cert_element, unexpected_size)
{
    int ret = 0;
    static const uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    uint8_t data[3];
    static const atcacert_cert_loc_t cert_loc = { .offset = 2, .count = sizeof(data) };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_get_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data) - 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);

    ret = atcacert_get_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, sizeof(data) + 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);
}

TEST(atcacert_get_cert_element, out_of_bounds)
{
    int ret = 0;
    static const uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    uint8_t data[sizeof(cert) * 2];
    atcacert_cert_loc_t cert_loc;
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    cert_loc.offset = 2;
    cert_loc.count = sizeof(cert);
    ret = atcacert_get_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, cert_loc.count);
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_OUT_OF_BOUNDS, ret);

    cert_loc.offset = 0;
    cert_loc.count = sizeof(cert) + 1;
    ret = atcacert_get_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), data, cert_loc.count);
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_OUT_OF_BOUNDS, ret);
}

TEST(atcacert_get_cert_element, bad_params)
{
    int ret = 0;
    static const uint8_t cert[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    uint8_t data[3];
    static const atcacert_cert_loc_t cert_loc = { .offset = 2, .count = sizeof(data) };
    atcacert_def_t cert_def;

    memset(&cert_def, 0, sizeof(cert_def));

    ret = atcacert_get_cert_element(NULL, &cert_loc, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_element(&cert_def, NULL, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_element(NULL, NULL, cert, sizeof(cert), data, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_element(&cert_def, &cert_loc, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_element(NULL, &cert_loc, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_element(&cert_def, NULL, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_element(NULL, NULL, cert, sizeof(cert), NULL, sizeof(data));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_subj_public_key);

TEST_SETUP(atcacert_set_subj_public_key)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_subj_public_key)
{
}

TEST(atcacert_set_subj_public_key, good)
{
    int ret = 0;
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x9F, 0x61, 0xEB,
        0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D,
        0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9, 0x20, 0x2D, 0x21,
        0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C,
        0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x84, 0x93, 0xB4, 0xC8, 0x5C, 0x54,
        0x69, 0x0C, 0xEC, 0xA0, 0x42, 0x41, 0x0C, 0x90, 0xE9, 0x71, 0x98, 0x66, 0xDC, 0x48, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_subj_public_key(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, g_test_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_set_subj_public_key, bad_params)
{
    int ret = 0;

    ret = atcacert_set_subj_public_key(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, g_test_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_subj_public_key(&g_cert_def, NULL, g_cert_def.cert_template_size, g_test_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_subj_public_key(NULL, NULL, g_cert_def.cert_template_size, g_test_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_subj_public_key(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_subj_public_key(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_subj_public_key(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_subj_public_key(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_subj_public_key);

TEST_SETUP(atcacert_get_subj_public_key)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_subj_public_key)
{
}

TEST(atcacert_get_subj_public_key, good)
{
    int ret = 0;
    static const uint8_t public_key_ref[64] = {
        0xF8, 0x0D, 0x8B, 0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B,
        0xA2, 0xA6, 0x59, 0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B,
        0x34, 0xF1, 0xB3, 0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92,
        0x01, 0x51, 0xD1, 0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31
    };
    uint8_t public_key[64];

    ret = atcacert_get_subj_public_key(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(public_key_ref, public_key, sizeof(public_key));
}

TEST(atcacert_get_subj_public_key, bad_params)
{
    int ret = 0;
    uint8_t public_key[64];

    ret = atcacert_get_subj_public_key(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_public_key(&g_cert_def, NULL, g_cert_def.cert_template_size, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_public_key(NULL, NULL, g_cert_def.cert_template_size, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_public_key(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_public_key(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_public_key(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_public_key(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_subj_key_id);

TEST_SETUP(atcacert_get_subj_key_id)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_subj_key_id)
{
}

TEST(atcacert_get_subj_key_id, good)
{
    int ret = 0;
    static const uint8_t key_id_ref[20] = {
        0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5,
        0xD2, 0x94, 0x65, 0xE2
    };
    uint8_t key_id[20];

    ret = atcacert_get_subj_key_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(key_id_ref, key_id, sizeof(key_id));
}

TEST(atcacert_get_subj_key_id, bad_params)
{
    int ret = 0;
    uint8_t key_id[20];

    ret = atcacert_get_subj_key_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_key_id(&g_cert_def, NULL, g_cert_def.cert_template_size, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_key_id(NULL, NULL, g_cert_def.cert_template_size, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_key_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_key_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_key_id(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_subj_key_id(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_signature);

TEST_SETUP(atcacert_set_signature)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_signature)
{
}

TEST(atcacert_set_signature, non_x509)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x63, 0xe6, 0xfd, 0xcc, 0x7a,
        0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25, 0x19, 0x2a, 0x10, 0x51, 0x99,
        0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e, 0xa9, 0x12, 0x89, 0xb5, 0xae,
        0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd, 0x15, 0xf2, 0xf5, 0x6f, 0x55,
        0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };
    static const size_t cert_template_size_ref = sizeof(cert_template_ref);
    size_t cert_template_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    g_cert_def.type = CERTTYPE_CUSTOM;
    g_cert_def.std_cert_elements[STDCERT_SIGNATURE].count = 64;

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(cert_template_size_ref, cert_template_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, cert_template_size);
}

TEST(atcacert_set_signature, x509_same_size)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7,
        0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48,
        0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    static const size_t cert_template_size_ref = sizeof(cert_template_ref);
    size_t cert_template_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(cert_template_size_ref, cert_template_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, cert_template_size);
}

TEST(atcacert_set_signature, x509_bigger)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0xF3, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB2, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46,
        0x02, 0x21, 0x00, 0xF3, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0,
        0x2F, 0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90,
        0x25, 0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1,
        0xC7, 0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF,
        0x48, 0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    static const size_t cert_template_size_ref = sizeof(cert_template_ref);
    size_t cert_template_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size + 1, sizeof(cert_template_ref));

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(cert_template_size_ref, cert_template_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, cert_template_size);
}

TEST(atcacert_set_signature, x509_smaller)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0x09, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB0, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x20, 0x09, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7, 0x44,
        0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48, 0x6B,
        0x89, 0xF0, 0xC6, 0xAF
    };
    static const size_t cert_template_size_ref = sizeof(cert_template_ref);
    size_t cert_template_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size - 1, sizeof(cert_template_ref));

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(cert_template_size_ref, cert_template_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, cert_template_size);
}

TEST(atcacert_set_signature, x509_smallest)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x72, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x09, 0x00, 0x30, 0x06,
        0x02, 0x01, 0x00, 0x02, 0x01, 0x00
    };
    static const size_t cert_template_size_ref = sizeof(cert_template_ref);
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(cert_template_size_ref, cert_template_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, cert_template_size);
}

TEST(atcacert_set_signature, x509_out_of_bounds)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0xF3, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    g_cert_def.std_cert_elements[STDCERT_SIGNATURE].offset = g_cert_def.cert_template_size;

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_OUT_OF_BOUNDS, ret);
}

TEST(atcacert_set_signature, x509_small_buf)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0xF3, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        cert_template_size,
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BUFFER_TOO_SMALL, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size + 1, cert_template_size);
}

TEST(atcacert_set_signature, x509_bad_cert_length)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0xF3, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    g_cert_def_cert_template[1] = 0x89;

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret);
}

TEST(atcacert_set_signature, x509_cert_length_change)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0xF3, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    g_cert_def_cert_template[1] = 0x01;

    ret = atcacert_set_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_CERT, ret);
}

TEST(atcacert_set_signature, bad_params)
{
    int ret = 0;
    static const uint8_t signature[64] = {
        0xF3, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_signature(NULL, g_cert_def_cert_template, &cert_template_size, sizeof(g_cert_def_cert_template), signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(&g_cert_def, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(NULL, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(&g_cert_def, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(NULL, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(&g_cert_def, NULL, NULL, sizeof(g_cert_def_cert_template), signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(NULL, NULL, NULL, sizeof(g_cert_def_cert_template), signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(&g_cert_def, g_cert_def_cert_template, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(NULL, g_cert_def_cert_template, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(&g_cert_def, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(NULL, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(&g_cert_def, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(NULL, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(&g_cert_def, NULL, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signature(NULL, NULL, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_signature);

TEST_SETUP(atcacert_get_signature)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_signature)
{
}

TEST(atcacert_get_signature, non_x509)
{
    int ret = 0;
    uint8_t signature[64];
    static const uint8_t signature_ref[64] = {
        0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93,
        0x7B, 0x37, 0x3F, 0x52, 0x6F, 0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2,
        0xF4, 0xC9, 0xE7, 0xCE, 0xDF, 0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C,
        0xD7, 0x9D, 0x5C, 0x43, 0xF4, 0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20
    };

    g_cert_def.type = CERTTYPE_CUSTOM;
    g_cert_def.std_cert_elements[STDCERT_SIGNATURE].count = 64;

    ret = atcacert_get_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(signature_ref, signature, sizeof(signature));
}

TEST(atcacert_get_signature, x509_no_padding)
{
    int ret = 0;
    uint8_t signature[64];
    static const uint8_t signature_ref[64] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0x09, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    static const uint8_t cert_template[] = {
        0x30, 0x82, 0x01, 0xB0, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x20, 0x09, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7, 0x44,
        0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48, 0x6B,
        0x89, 0xF0, 0xC6, 0xAF
    };

    ret = atcacert_get_signature(
        &g_cert_def,
        cert_template,
        sizeof(cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(signature_ref, signature, sizeof(signature));
}

TEST(atcacert_get_signature, x509_r_padding)
{
    int ret = 0;
    uint8_t signature[64];
    static const uint8_t signature_ref[64] = {
        0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F, 0xF6, 0x5C,
        0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF, 0x24, 0xAA,
        0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4, 0xA9, 0x1B, 0xB3, 0xB1, 0xC7,
        0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77, 0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    ret = atcacert_get_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(signature_ref, signature, sizeof(signature));
}

TEST(atcacert_get_signature, x509_rs_padding)
{
    int ret = 0;
    uint8_t signature[64];
    static const uint8_t signature_ref[64] = {
        0xF3, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf
    };
    static const uint8_t cert_template[] = {
        0x30, 0x82, 0x01, 0xB2, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46,
        0x02, 0x21, 0x00, 0xF3, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0,
        0x2F, 0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90,
        0x25, 0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1,
        0xC7, 0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF,
        0x48, 0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };

    ret = atcacert_get_signature(
        &g_cert_def,
        cert_template,
        sizeof(cert_template),
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(signature_ref, signature, sizeof(signature));
}

TEST(atcacert_get_signature, x509_bad_sig)
{
    int ret = 0;
    uint8_t signature[64];
    static const uint8_t cert_template[] = {
        0x30, 0x82, 0x01, 0xB0, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x20, 0x09, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7, 0x44,
        0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48, 0x6B,
        0x89, 0xF0, 0xC6, 0xAF
    };

    ret = atcacert_get_signature(
        &g_cert_def,
        cert_template,
        sizeof(cert_template) - 1,
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret);
}

TEST(atcacert_get_signature, x509_out_of_bounds)
{
    int ret = 0;
    uint8_t signature[64];

    g_cert_def.std_cert_elements[STDCERT_SIGNATURE].offset = g_cert_def.cert_template_size;

    ret = atcacert_get_signature(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_OUT_OF_BOUNDS, ret);
}

TEST(atcacert_get_signature, x509_bad_params)
{
    int ret = 0;
    uint8_t signature[64];

    ret = atcacert_get_signature(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signature(&g_cert_def, NULL, g_cert_def.cert_template_size, signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signature(NULL, NULL, g_cert_def.cert_template_size, signature);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signature(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signature(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signature(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signature(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_issue_date);

TEST_SETUP(atcacert_set_issue_date)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_issue_date)
{
}

TEST(atcacert_set_issue_date, good)
{
    int ret = 0;
    static const atcacert_tm_utc_t date = {
        .tm_year    = 2012 - 1900,
        .tm_mon     = 11 - 1,
        .tm_mday    = 10,
        .tm_hour    = 9,
        .tm_min     = 8,
        .tm_sec     = 7
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x32, 0x31, 0x31, 0x31, 0x30,
        0x30, 0x39, 0x30, 0x38, 0x30, 0x37, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_issue_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_set_issue_date, bad_params)
{
    int ret = 0;
    static const atcacert_tm_utc_t date = {
        .tm_year    = 2012 - 1900,
        .tm_mon     = 11 - 1,
        .tm_mday    = 10,
        .tm_hour    = 9,
        .tm_min     = 8,
        .tm_sec     = 7
    };

    ret = atcacert_set_issue_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_issue_date(&g_cert_def, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_issue_date(NULL, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_issue_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_issue_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_issue_date(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_issue_date(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_issue_date);

TEST_SETUP(atcacert_get_issue_date)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_issue_date)
{
}

TEST(atcacert_get_issue_date, good)
{
    int ret = 0;
    atcacert_tm_utc_t date;
    static const atcacert_tm_utc_t date_ref = {
        .tm_year    = 2015 - 1900,
        .tm_mon     = 7 - 1,
        .tm_mday    = 31,
        .tm_hour    = 0,
        .tm_min     = 12,
        .tm_sec     = 15
    };

    ret = atcacert_get_issue_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(&date_ref, &date, sizeof(date));
}

TEST(atcacert_get_issue_date, bad_params)
{
    int ret = 0;
    atcacert_tm_utc_t date;

    ret = atcacert_get_issue_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_issue_date(&g_cert_def, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_issue_date(NULL, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_issue_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_issue_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_issue_date(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_issue_date(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_expire_date);

TEST_SETUP(atcacert_set_expire_date)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_expire_date)
{
}

TEST(atcacert_set_expire_date, good)
{
    int ret = 0;
    static const atcacert_tm_utc_t date = {
        .tm_year    = 2012 - 1900,
        .tm_mon     = 11 - 1,
        .tm_mday    = 10,
        .tm_hour    = 9,
        .tm_min     = 8,
        .tm_sec     = 7
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x31, 0x32, 0x31, 0x31, 0x31, 0x30, 0x30,
        0x39, 0x30, 0x38, 0x30, 0x37, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_expire_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_set_expire_date, bad_params)
{
    int ret = 0;
    static const atcacert_tm_utc_t date = {
        .tm_year    = 2012 - 1900,
        .tm_mon     = 11 - 1,
        .tm_mday    = 10,
        .tm_hour    = 9,
        .tm_min     = 8,
        .tm_sec     = 7
    };

    ret = atcacert_set_expire_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_expire_date(&g_cert_def, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_expire_date(NULL, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_expire_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_expire_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_expire_date(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_expire_date(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_expire_date);

TEST_SETUP(atcacert_get_expire_date)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_expire_date)
{
}

TEST(atcacert_get_expire_date, good)
{
    int ret = 0;
    atcacert_tm_utc_t date;
    static const atcacert_tm_utc_t date_ref = {
        .tm_year    = 2035 - 1900,
        .tm_mon     = 7 - 1,
        .tm_mday    = 31,
        .tm_hour    = 0,
        .tm_min     = 12,
        .tm_sec     = 15
    };

    ret = atcacert_get_expire_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(&date_ref, &date, sizeof(date));
}

TEST(atcacert_get_expire_date, bad_params)
{
    int ret = 0;
    atcacert_tm_utc_t date;

    ret = atcacert_get_expire_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_expire_date(&g_cert_def, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_expire_date(NULL, NULL, g_cert_def.cert_template_size, &date);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_expire_date(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_expire_date(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_expire_date(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_expire_date(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_signer_id);

TEST_SETUP(atcacert_set_signer_id)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_signer_id)
{
}

TEST(atcacert_set_signer_id, good)
{
    int ret = 0;
    static const uint8_t signer_id[2] = { 0x07, 0xAF };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x30, 0x37,
        0x41, 0x46, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_signer_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_set_signer_id, bad_params)
{
    int ret = 0;
    static const uint8_t signer_id[2] = { 0x07, 0xAF };

    ret = atcacert_set_signer_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signer_id(&g_cert_def, NULL, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signer_id(NULL, NULL, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signer_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signer_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signer_id(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_signer_id(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_signer_id);

TEST_SETUP(atcacert_get_signer_id)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_signer_id)
{
}

TEST(atcacert_get_signer_id, uppercase)
{
    int ret = 0;
    uint8_t signer_id[2];
    static const uint8_t signer_id_ref[2] = { 0xC4, 0x8B };
    static const uint8_t cert_template[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34,
        0x38, 0x42, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    ret = atcacert_get_signer_id(&g_cert_def, cert_template, sizeof(cert_template), signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(signer_id_ref, signer_id, sizeof(signer_id));
}

TEST(atcacert_get_signer_id, lowercase)
{
    int ret = 0;
    uint8_t signer_id[2];
    static const uint8_t signer_id_ref[2] = { 0xC4, 0x8B };
    static const uint8_t cert_template[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x63, 0x34,
        0x38, 0x62, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    ret = atcacert_get_signer_id(&g_cert_def, cert_template, sizeof(cert_template), signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(signer_id_ref, signer_id, sizeof(signer_id));
}

TEST(atcacert_get_signer_id, invalid)
{
    int ret = 0;
    uint8_t signer_id[2];

    ret = atcacert_get_signer_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret);
}

TEST(atcacert_get_signer_id, bad_params)
{
    int ret = 0;
    uint8_t signer_id[2];

    ret = atcacert_get_signer_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signer_id(&g_cert_def, NULL, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signer_id(NULL, NULL, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signer_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signer_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signer_id(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_signer_id(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_cert_sn);

TEST_SETUP(atcacert_set_cert_sn)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_cert_sn)
{
}

TEST(atcacert_set_cert_sn, good)
{
    int ret = 0;
    static const uint8_t cert_sn[3] = { 0x01, 0x02, 0x03 };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01,
        0x02, 0x03, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };
    size_t cert_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        cert_sn,
        sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_set_cert_sn, unexpected_size)
{
    int ret = 0;
    static const uint8_t cert_sn[3] = { 0x01, 0x02, 0x03 };
    size_t cert_size = g_cert_def.cert_template_size;

    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        cert_sn,
        sizeof(cert_sn) + 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);
}

TEST(atcacert_set_cert_sn, bad_params)
{
    int ret = 0;
    static const uint8_t cert_sn[3] = { 0x01, 0x02, 0x03 };
    size_t cert_size = g_cert_def.cert_template_size;

    ret = atcacert_set_cert_sn(NULL, g_cert_def_cert_template, &cert_size, sizeof(g_cert_def_cert_template), cert_sn, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(&g_cert_def, NULL, &cert_size, sizeof(g_cert_def_cert_template), cert_sn, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(NULL, NULL, &cert_size, sizeof(g_cert_def_cert_template), cert_sn, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(&g_cert_def, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), cert_sn, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(NULL, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), cert_sn, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(&g_cert_def, NULL, NULL, sizeof(g_cert_def_cert_template), cert_sn, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(NULL, NULL, NULL, sizeof(g_cert_def_cert_template), cert_sn, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(&g_cert_def, g_cert_def_cert_template, &cert_size, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(NULL, g_cert_def_cert_template, &cert_size, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(&g_cert_def, NULL, &cert_size, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(NULL, NULL, &cert_size, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(&g_cert_def, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(NULL, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(&g_cert_def, NULL, NULL, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_cert_sn(NULL, NULL, NULL, sizeof(g_cert_def_cert_template), NULL, sizeof(cert_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_gen_cert_sn);

TEST_SETUP(atcacert_gen_cert_sn)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_gen_cert_sn)
{
}

TEST(atcacert_gen_cert_sn, stored)
{
    int ret = 0;
    uint8_t cert_ref[512];

    memcpy(cert_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);

    g_cert_def.sn_source = SNSRC_STORED;

    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, stored_bad_params)
{
    int ret = 0;

    g_cert_def.sn_source = SNSRC_STORED;

    ret = atcacert_gen_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

TEST(atcacert_gen_cert_sn, device_sn)
{
    int ret = 0;
    uint8_t clear_sn[10];
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x40,
        0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0xC3, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44,
        0x89, 0xD1, 0x70, 0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68,
        0x32, 0xDC, 0x59, 0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE,
        0x21, 0xC3, 0x4F, 0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE,
        0x36, 0xE2, 0x31, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3,
        0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5E, 0x13, 0x59, 0x05, 0x08,
        0xDA, 0x03, 0xFD, 0x94, 0x1B, 0xAF, 0xEF, 0x8A, 0x3D, 0xC8, 0x24, 0xE5, 0x49, 0x07, 0xB8, 0xA2,
        0xBD, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xE1, 0xAA, 0x02, 0x21, 0x00, 0x96, 0xFF,
        0x2B, 0xDF, 0x34, 0x54, 0x9B, 0x7C, 0x56, 0x8F, 0x54, 0x44, 0x4F, 0xE6, 0xAD, 0x3B, 0xFE, 0x63,
        0xBD, 0xD2, 0x93, 0x65, 0xF2, 0x65, 0x59, 0x22, 0xC6, 0x25, 0x90, 0x7A, 0xEC, 0x19
    };
    size_t cert_size;

    useCert(&g_test_cert_def_0_device);
    cert_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, device_sn_unexpected_size)
{
    int ret = 0;
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };

    useCert(&g_test_cert_def_0_device);

    g_cert_def.std_cert_elements[STDCERT_CERT_SN].count = 10 - 1;
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);

    g_cert_def.std_cert_elements[STDCERT_CERT_SN].count = 10 + 1;
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);
}

TEST(atcacert_gen_cert_sn, device_sn_bad_params)
{
    int ret = 0;
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };

    useCert(&g_test_cert_def_0_device);

    ret = atcacert_gen_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, NULL, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

TEST(atcacert_gen_cert_sn, signer_id)
{
    int ret = 0;
    uint8_t clear_sn[3];
    static const uint8_t signer_id[2] = { 0xC4, 0x8B };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0xC4, 0x8B, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34,
        0x38, 0x42, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };
    size_t cert_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_set_signer_id(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, signer_id_unexpected_size)
{
    int ret = 0;
    static const uint8_t signer_id[2] = { 0xC4, 0x8B };

    ret = atcacert_set_signer_id(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    g_cert_def.std_cert_elements[STDCERT_CERT_SN].count = 3 - 1;
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);

    g_cert_def.std_cert_elements[STDCERT_CERT_SN].count = 3 + 1;
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);
}

TEST(atcacert_gen_cert_sn, signer_id_bad_signer_id)
{
    int ret = 0;

    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret);
}

TEST(atcacert_gen_cert_sn, signer_id_bad_params)
{
    int ret = 0;
    static const uint8_t signer_id[2] = { 0xC4, 0x8B };

    ret = atcacert_set_signer_id(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_gen_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

static const uint8_t g_hash_public_key[64] = {
    0x27, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44, 0x89, 0xD1, 0x70,
    0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68, 0x32, 0xDC, 0x59,
    0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE, 0x21, 0xC3, 0x4F,
    0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE, 0x36, 0xE2, 0x31
};

TEST(atcacert_gen_cert_sn, pub_key_hash)
{
    int ret = 0;
    uint8_t clear_sn[10];
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x72,
        0x69, 0xB4, 0x59, 0x76, 0x63, 0xFD, 0xD5, 0xBD, 0x45, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x27, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44,
        0x89, 0xD1, 0x70, 0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68,
        0x32, 0xDC, 0x59, 0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE,
        0x21, 0xC3, 0x4F, 0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE,
        0x36, 0xE2, 0x31, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3,
        0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5E, 0x13, 0x59, 0x05, 0x08,
        0xDA, 0x03, 0xFD, 0x94, 0x1B, 0xAF, 0xEF, 0x8A, 0x3D, 0xC8, 0x24, 0xE5, 0x49, 0x07, 0xB8, 0xA2,
        0xBD, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xE1, 0xAA, 0x02, 0x21, 0x00, 0x96, 0xFF,
        0x2B, 0xDF, 0x34, 0x54, 0x9B, 0x7C, 0x56, 0x8F, 0x54, 0x44, 0x4F, 0xE6, 0xAD, 0x3B, 0xFE, 0x63,
        0xBD, 0xD2, 0x93, 0x65, 0xF2, 0x65, 0x59, 0x22, 0xC6, 0x25, 0x90, 0x7A, 0xEC, 0x19
    };
    size_t cert_size;

    useCert(&g_test_cert_def_0_device);
    cert_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    g_cert_def.sn_source = SNSRC_PUB_KEY_HASH;

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_set_subj_public_key(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        g_hash_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}


TEST(atcacert_gen_cert_sn, pub_key_hash_pos)
{
    int ret = 0;
    uint8_t clear_sn[10];
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x32,
        0x69, 0xB4, 0x59, 0x76, 0x63, 0xFD, 0xD5, 0xBD, 0x45, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x27, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44,
        0x89, 0xD1, 0x70, 0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68,
        0x32, 0xDC, 0x59, 0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE,
        0x21, 0xC3, 0x4F, 0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE,
        0x36, 0xE2, 0x31, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3,
        0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5E, 0x13, 0x59, 0x05, 0x08,
        0xDA, 0x03, 0xFD, 0x94, 0x1B, 0xAF, 0xEF, 0x8A, 0x3D, 0xC8, 0x24, 0xE5, 0x49, 0x07, 0xB8, 0xA2,
        0xBD, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xE1, 0xAA, 0x02, 0x21, 0x00, 0x96, 0xFF,
        0x2B, 0xDF, 0x34, 0x54, 0x9B, 0x7C, 0x56, 0x8F, 0x54, 0x44, 0x4F, 0xE6, 0xAD, 0x3B, 0xFE, 0x63,
        0xBD, 0xD2, 0x93, 0x65, 0xF2, 0x65, 0x59, 0x22, 0xC6, 0x25, 0x90, 0x7A, 0xEC, 0x19
    };
    size_t cert_size;

    useCert(&g_test_cert_def_0_device);
    cert_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    g_cert_def.sn_source = SNSRC_PUB_KEY_HASH_POS;

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_set_subj_public_key(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        g_hash_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, pub_key_hash_raw)
{
    int ret = 0;
    uint8_t clear_sn[10];
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0xB2,
        0x69, 0xB4, 0x59, 0x76, 0x63, 0xFD, 0xD5, 0xBD, 0x45, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x27, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44,
        0x89, 0xD1, 0x70, 0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68,
        0x32, 0xDC, 0x59, 0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE,
        0x21, 0xC3, 0x4F, 0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE,
        0x36, 0xE2, 0x31, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3,
        0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5E, 0x13, 0x59, 0x05, 0x08,
        0xDA, 0x03, 0xFD, 0x94, 0x1B, 0xAF, 0xEF, 0x8A, 0x3D, 0xC8, 0x24, 0xE5, 0x49, 0x07, 0xB8, 0xA2,
        0xBD, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xE1, 0xAA, 0x02, 0x21, 0x00, 0x96, 0xFF,
        0x2B, 0xDF, 0x34, 0x54, 0x9B, 0x7C, 0x56, 0x8F, 0x54, 0x44, 0x4F, 0xE6, 0xAD, 0x3B, 0xFE, 0x63,
        0xBD, 0xD2, 0x93, 0x65, 0xF2, 0x65, 0x59, 0x22, 0xC6, 0x25, 0x90, 0x7A, 0xEC, 0x19
    };
    size_t cert_size;

    useCert(&g_test_cert_def_0_device);
    cert_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    g_cert_def.sn_source = SNSRC_PUB_KEY_HASH_RAW;

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_set_subj_public_key(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        g_hash_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, pub_key_hash_unexpected_size)
{
    int ret = 0;

    useCert(&g_test_cert_def_0_device);

    g_cert_def.sn_source = SNSRC_PUB_KEY_HASH;

    g_cert_def.std_cert_elements[STDCERT_CERT_SN].count = 33;
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);
}

TEST(atcacert_gen_cert_sn, pub_key_hash_bad_public_key)
{
    int ret = 0;

    useCert(&g_test_cert_def_0_device);

    g_cert_def.sn_source = SNSRC_PUB_KEY_HASH;

    g_cert_def.std_cert_elements[STDCERT_PUBLIC_KEY].count = 0;
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_ELEM_MISSING, ret);
}

TEST(atcacert_gen_cert_sn, pub_key_hash_bad_issue_date)
{
    int ret = 0;

    useCert(&g_test_cert_def_0_device);

    g_cert_def.sn_source = SNSRC_PUB_KEY_HASH;

    g_cert_def_cert_template[105] = 'A';
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret);
}

TEST(atcacert_gen_cert_sn, pub_key_hash_bad_params)
{
    int ret = 0;

    useCert(&g_test_cert_def_0_device);

    g_cert_def.sn_source = SNSRC_PUB_KEY_HASH;

    ret = atcacert_gen_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

TEST(atcacert_gen_cert_sn, device_sn_hash)
{
    int ret = 0;
    uint8_t clear_sn[10];
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x73,
        0x51, 0xA9, 0x79, 0xD7, 0xCA, 0xCC, 0xA4, 0xA7, 0xD2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0xC3, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44,
        0x89, 0xD1, 0x70, 0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68,
        0x32, 0xDC, 0x59, 0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE,
        0x21, 0xC3, 0x4F, 0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE,
        0x36, 0xE2, 0x31, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3,
        0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5E, 0x13, 0x59, 0x05, 0x08,
        0xDA, 0x03, 0xFD, 0x94, 0x1B, 0xAF, 0xEF, 0x8A, 0x3D, 0xC8, 0x24, 0xE5, 0x49, 0x07, 0xB8, 0xA2,
        0xBD, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xE1, 0xAA, 0x02, 0x21, 0x00, 0x96, 0xFF,
        0x2B, 0xDF, 0x34, 0x54, 0x9B, 0x7C, 0x56, 0x8F, 0x54, 0x44, 0x4F, 0xE6, 0xAD, 0x3B, 0xFE, 0x63,
        0xBD, 0xD2, 0x93, 0x65, 0xF2, 0x65, 0x59, 0x22, 0xC6, 0x25, 0x90, 0x7A, 0xEC, 0x19
    };
    size_t cert_size;

    useCert(&g_test_cert_def_0_device);
    cert_size = g_cert_def.cert_template_size;

    g_cert_def.sn_source = SNSRC_DEVICE_SN_HASH;
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, device_sn_hash_pos)
{
    int ret = 0;
    uint8_t clear_sn[10];
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x33,
        0x51, 0xA9, 0x79, 0xD7, 0xCA, 0xCC, 0xA4, 0xA7, 0xD2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0xC3, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44,
        0x89, 0xD1, 0x70, 0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68,
        0x32, 0xDC, 0x59, 0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE,
        0x21, 0xC3, 0x4F, 0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE,
        0x36, 0xE2, 0x31, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3,
        0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5E, 0x13, 0x59, 0x05, 0x08,
        0xDA, 0x03, 0xFD, 0x94, 0x1B, 0xAF, 0xEF, 0x8A, 0x3D, 0xC8, 0x24, 0xE5, 0x49, 0x07, 0xB8, 0xA2,
        0xBD, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xE1, 0xAA, 0x02, 0x21, 0x00, 0x96, 0xFF,
        0x2B, 0xDF, 0x34, 0x54, 0x9B, 0x7C, 0x56, 0x8F, 0x54, 0x44, 0x4F, 0xE6, 0xAD, 0x3B, 0xFE, 0x63,
        0xBD, 0xD2, 0x93, 0x65, 0xF2, 0x65, 0x59, 0x22, 0xC6, 0x25, 0x90, 0x7A, 0xEC, 0x19
    };
    size_t cert_size;

    useCert(&g_test_cert_def_0_device);
    cert_size = g_cert_def.cert_template_size;

    g_cert_def.sn_source = SNSRC_DEVICE_SN_HASH_POS;
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, device_sn_hash_raw)
{
    int ret = 0;
    uint8_t clear_sn[10];
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0xB3,
        0x51, 0xA9, 0x79, 0xD7, 0xCA, 0xCC, 0xA4, 0xA7, 0xD2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0xC3, 0xDC, 0x86, 0xE9, 0xCC, 0x59, 0xA1, 0xFA, 0xF8, 0xE6, 0x02, 0xB3, 0x44,
        0x89, 0xD1, 0x70, 0x4A, 0x3B, 0x44, 0x04, 0x52, 0xAA, 0x11, 0x93, 0x35, 0xA9, 0xBE, 0x6F, 0x68,
        0x32, 0xDC, 0x59, 0xCE, 0x5E, 0x74, 0x73, 0xB8, 0x44, 0xBD, 0x08, 0x4D, 0x5D, 0x3D, 0xE5, 0xDE,
        0x21, 0xC3, 0x4F, 0x8D, 0xC1, 0x61, 0x4F, 0x17, 0x27, 0xAF, 0x6D, 0xC4, 0x9C, 0x42, 0x83, 0xEE,
        0x36, 0xE2, 0x31, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F, 0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3,
        0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5E, 0x13, 0x59, 0x05, 0x08,
        0xDA, 0x03, 0xFD, 0x94, 0x1B, 0xAF, 0xEF, 0x8A, 0x3D, 0xC8, 0x24, 0xE5, 0x49, 0x07, 0xB8, 0xA2,
        0xBD, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xE1, 0xAA, 0x02, 0x21, 0x00, 0x96, 0xFF,
        0x2B, 0xDF, 0x34, 0x54, 0x9B, 0x7C, 0x56, 0x8F, 0x54, 0x44, 0x4F, 0xE6, 0xAD, 0x3B, 0xFE, 0x63,
        0xBD, 0xD2, 0x93, 0x65, 0xF2, 0x65, 0x59, 0x22, 0xC6, 0x25, 0x90, 0x7A, 0xEC, 0x19
    };
    size_t cert_size;

    useCert(&g_test_cert_def_0_device);
    cert_size = g_cert_def.cert_template_size;

    g_cert_def.sn_source = SNSRC_DEVICE_SN_HASH_RAW;
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    memset(clear_sn, 0, sizeof(clear_sn));
    ret = atcacert_set_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_size,
        sizeof(g_cert_def_cert_template),
        clear_sn,
        sizeof(clear_sn));
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, cert_size);

    ret = atcacert_gen_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, g_cert_def.cert_template_size);
}

TEST(atcacert_gen_cert_sn, device_sn_hash_unexpected_size)
{
    int ret = 0;
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };

    useCert(&g_test_cert_def_0_device);

    g_cert_def.sn_source = SNSRC_DEVICE_SN_HASH;

    g_cert_def.std_cert_elements[STDCERT_CERT_SN].count = 33;
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_UNEXPECTED_ELEM_SIZE, ret);
}

TEST(atcacert_gen_cert_sn, device_sn_hash_bad_issue_date)
{
    int ret = 0;
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };

    useCert(&g_test_cert_def_0_device);

    g_cert_def.sn_source = SNSRC_DEVICE_SN_HASH;

    g_cert_def_cert_template[105] = 'A';
    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret);
}

TEST(atcacert_gen_cert_sn, device_sn_hash_bad_params)
{
    int ret = 0;
    static const uint8_t device_sn[9] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12 };

    useCert(&g_test_cert_def_0_device);

    g_cert_def.sn_source = SNSRC_DEVICE_SN_HASH;

    ret = atcacert_gen_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, NULL, g_cert_def.cert_template_size, device_sn);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_gen_cert_sn(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_cert_sn);

TEST_SETUP(atcacert_get_cert_sn)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_cert_sn)
{
}

TEST(atcacert_get_cert_sn, good)
{
    int ret = 0;
    uint8_t cert_sn[32];
    size_t cert_sn_size = sizeof(cert_sn);
    static const uint8_t cert_sn_ref[3] = { 0x40, 0x01, 0x02 };

    TEST_ASSERT(g_cert_def.std_cert_elements[STDCERT_CERT_SN].count <= sizeof(cert_sn));

    ret = atcacert_get_cert_sn(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        cert_sn,
        &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_sn_ref), cert_sn_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_sn_ref, cert_sn, sizeof(cert_sn_ref));
}

TEST(atcacert_get_cert_sn, bad_params)
{
    int ret = 0;
    uint8_t cert_sn[32];
    size_t cert_sn_size = sizeof(cert_sn);

    ret = atcacert_get_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, cert_sn, &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, cert_sn, &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(NULL, NULL, g_cert_def.cert_template_size, cert_sn, &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL, &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(NULL, NULL, g_cert_def.cert_template_size, NULL, &cert_sn_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, cert_sn, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, cert_sn, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, cert_sn, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(NULL, NULL, g_cert_def.cert_template_size, cert_sn, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_cert_sn(NULL, NULL, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_set_auth_key_id);

TEST_SETUP(atcacert_set_auth_key_id)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_auth_key_id)
{
}

static const uint8_t g_ca_public_key[64] = {
    0x37, 0x0e, 0x32, 0x51, 0x2f, 0x52, 0x48, 0xcc, 0x30, 0x7b, 0x4d, 0x3c, 0x38, 0x61, 0x7f, 0xe7,
    0x2e, 0x3b, 0xfa, 0x0f, 0xa4, 0x2b, 0xfc, 0xb5, 0x16, 0xed, 0xee, 0xea, 0x22, 0x67, 0xb9, 0x76,
    0x03, 0xd6, 0x25, 0x3f, 0xc2, 0xe1, 0xb6, 0x4d, 0xb1, 0xbc, 0xe1, 0xa9, 0x31, 0x4e, 0x38, 0x86,
    0x2f, 0x4f, 0xfa, 0x02, 0x4f, 0xf9, 0x95, 0x6d, 0xb4, 0x81, 0x45, 0x83, 0x5c, 0x1f, 0x1c, 0x35
};

TEST(atcacert_set_auth_key_id, good)
{
    int ret = 0;
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x17, 0x0D, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4F, 0xAA, 0x04, 0x1C, 0xBC,
        0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42, 0xBB, 0xB9, 0x5B, 0x51, 0x81, 0x19, 0x27, 0x6D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F,
        0xF6, 0x5C, 0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF,
        0x24, 0xAA, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4,
        0xA9, 0x1B, 0xB3, 0xB1, 0xC7, 0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77,
        0x6C, 0xA9, 0xC7, 0x79, 0x0D
    };

    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_auth_key_id(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, sizeof(cert_template_ref));
}

TEST(atcacert_set_auth_key_id, bad_params)
{
    int ret = 0;

    ret = atcacert_set_auth_key_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, g_test_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_auth_key_id(&g_cert_def, NULL, g_cert_def.cert_template_size, g_test_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_auth_key_id(NULL, NULL, g_cert_def.cert_template_size, g_test_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_auth_key_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_auth_key_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_auth_key_id(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_auth_key_id(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_auth_key_id);

TEST_SETUP(atcacert_get_auth_key_id)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_auth_key_id)
{
}

TEST(atcacert_get_auth_key_id, good)
{
    int ret = 0;
    uint8_t key_id[20];
    static const uint8_t key_id_ref[20] = {
        0x77, 0x23, 0xA2, 0xC4, 0x32, 0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D,
        0xD2, 0xBE, 0x95, 0x5D
    };

    ret = atcacert_get_auth_key_id(
        &g_cert_def,
        g_cert_def_cert_template,
        g_cert_def.cert_template_size,
        key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(key_id_ref, key_id, sizeof(key_id));
}

TEST(atcacert_get_auth_key_id, bad_params)
{
    int ret = 0;
    uint8_t key_id[20];

    ret = atcacert_get_auth_key_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_auth_key_id(&g_cert_def, NULL, g_cert_def.cert_template_size, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_auth_key_id(NULL, NULL, g_cert_def.cert_template_size, key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_auth_key_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_auth_key_id(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_auth_key_id(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_auth_key_id(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

static const uint8_t g_comp_cert[72] = {
    0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
    0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
    0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
    0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
    0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x10, 0x90, 0x00
};


TEST_GROUP(atcacert_set_comp_cert);

TEST_SETUP(atcacert_set_comp_cert)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_set_comp_cert)
{
}

TEST(atcacert_set_comp_cert, same_size)
{
    int ret = 0;
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37,
        0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x34, 0x39, 0x30, 0x33, 0x30, 0x37, 0x31,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34,
        0x38, 0x42, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7,
        0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48,
        0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(cert_template_size, sizeof(cert_template_ref));

    ret = atcacert_set_comp_cert(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(cert_template_size, sizeof(cert_template_ref));
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, sizeof(cert_template_ref));
}

TEST(atcacert_set_comp_cert, bigger)
{
    int ret = 0;
    static const uint8_t comp_cert[72] = {
        0x83, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x10, 0x90, 0x00
    };
    static const uint8_t cert_template_ref[] = {
        0x30, 0x82, 0x01, 0xB2, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37,
        0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x34, 0x39, 0x30, 0x33, 0x30, 0x37, 0x31,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34,
        0x38, 0x42, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF8, 0x0D, 0x8B,
        0x65, 0xE8, 0xBC, 0xCE, 0x14, 0x76, 0xE1, 0x8D, 0x05, 0xE2, 0x01, 0x69, 0x3B, 0xA2, 0xA6, 0x59,
        0xCF, 0xB9, 0xFD, 0x95, 0xE7, 0xBA, 0xD0, 0x21, 0x77, 0xF1, 0x38, 0x76, 0x1B, 0x34, 0xF1, 0xB3,
        0x58, 0x95, 0xA1, 0x35, 0x0D, 0x94, 0x82, 0x47, 0xE5, 0x23, 0x6F, 0xB3, 0x92, 0x01, 0x51, 0xD1,
        0x3A, 0x6F, 0x01, 0x23, 0xD6, 0x70, 0xB5, 0xE5, 0x0C, 0xE0, 0xFF, 0x49, 0x31, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x1F, 0xAF, 0x8F, 0x90, 0x86, 0x5F,
        0x7D, 0xD2, 0x26, 0xB0, 0x6F, 0xE3, 0x20, 0x4E, 0x48, 0xA5, 0xD2, 0x94, 0x65, 0xE2, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xA2, 0xC4, 0x32,
        0xA6, 0x94, 0x1D, 0x81, 0x32, 0xCB, 0x76, 0x04, 0xC3, 0x80, 0x1D, 0xD2, 0xBE, 0x95, 0x5D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46,
        0x02, 0x21, 0x00, 0x83, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0,
        0x2F, 0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90,
        0x25, 0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1,
        0xC7, 0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF,
        0x48, 0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    TEST_ASSERT_EQUAL(cert_template_size + 1, sizeof(cert_template_ref));

    ret = atcacert_set_comp_cert(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(cert_template_size, sizeof(cert_template_ref));
    TEST_ASSERT_EQUAL_MEMORY(cert_template_ref, g_cert_def_cert_template, sizeof(cert_template_ref));
}

TEST(atcacert_set_comp_cert, bad_format)
{
    int ret = 0;
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x10, 0x91, 0x00
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_comp_cert(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_DECODING_ERROR, ret);
}

TEST(atcacert_set_comp_cert, bad_template_id)
{
    int ret = 0;
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x20, 0x90, 0x00
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_comp_cert(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_WRONG_CERT_DEF, ret);
}

TEST(atcacert_set_comp_cert, bad_chain_id)
{
    int ret = 0;
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x11, 0x90, 0x00
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_comp_cert(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_WRONG_CERT_DEF, ret);
}

TEST(atcacert_set_comp_cert, bad_sn_source)
{
    int ret = 0;
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x10, 0xC0, 0x00
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_comp_cert(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_WRONG_CERT_DEF, ret);
}

TEST(atcacert_set_comp_cert, bad_enc_dates)
{
    int ret = 0;
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xAF, 0x9D, 0x5C, 0xC4, 0x8B, 0x10, 0x90, 0x00
    };
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_comp_cert(
        &g_cert_def,
        g_cert_def_cert_template,
        &cert_template_size,
        sizeof(g_cert_def_cert_template),
        comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_INVALID_DATE, ret);
}

TEST(atcacert_set_comp_cert, bad_params)
{
    int ret = 0;
    size_t cert_template_size = g_cert_def.cert_template_size;

    ret = atcacert_set_comp_cert(NULL, g_cert_def_cert_template, &cert_template_size, sizeof(g_cert_def_cert_template), g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(&g_cert_def, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(NULL, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(&g_cert_def, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(NULL, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(&g_cert_def, NULL, NULL, sizeof(g_cert_def_cert_template), g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(NULL, NULL, NULL, sizeof(g_cert_def_cert_template), g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(&g_cert_def, g_cert_def_cert_template, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(NULL, g_cert_def_cert_template, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(&g_cert_def, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(NULL, NULL, &cert_template_size, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(&g_cert_def, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(NULL, g_cert_def_cert_template, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(&g_cert_def, NULL, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_set_comp_cert(NULL, NULL, NULL, sizeof(g_cert_def_cert_template), NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_comp_cert);

TEST_SETUP(atcacert_get_comp_cert)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_comp_cert)
{
}

TEST(atcacert_get_comp_cert, good)
{
    int ret = 0;
    uint8_t comp_cert[72];
    static const uint8_t comp_cert_ref[72] = {
        0x43, 0x90, 0xCD, 0x89, 0xE0, 0x75, 0xD0, 0x45, 0x93, 0x7B, 0x37, 0x3F, 0x52, 0x6F, 0xF6, 0x5C,
        0x4B, 0x4C, 0xCA, 0x7C, 0x61, 0x3C, 0x5F, 0x9C, 0xF2, 0xF4, 0xC9, 0xE7, 0xCE, 0xDF, 0x24, 0xAA,
        0x89, 0x52, 0x36, 0xF3, 0xC3, 0x7C, 0xD7, 0x9D, 0x5C, 0x43, 0xF4, 0xA9, 0x1B, 0xB3, 0xB1, 0xC7,
        0x3E, 0xB2, 0x66, 0x74, 0x6C, 0x20, 0x53, 0x0A, 0x3B, 0x90, 0x77, 0x6C, 0xA9, 0xC7, 0x79, 0x0D,
        0x7B, 0xFC, 0x14, 0xC4, 0x8B, 0x14, 0x90, 0x00
    };
    static const uint8_t signer_id[2] = { 0xC4, 0x8B };

    g_cert_def.chain_id = 4;

    ret = atcacert_set_signer_id(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, signer_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_get_comp_cert(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(comp_cert_ref, comp_cert, sizeof(comp_cert));
}

TEST(atcacert_get_comp_cert, bad_params)
{
    int ret = 0;
    uint8_t comp_cert[72];

    ret = atcacert_get_comp_cert(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_comp_cert(&g_cert_def, NULL, g_cert_def.cert_template_size, comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_comp_cert(NULL, NULL, g_cert_def.cert_template_size, comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_comp_cert(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_comp_cert(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_comp_cert(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_comp_cert(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_tbs);

TEST_SETUP(atcacert_get_tbs)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_tbs)
{
}

TEST(atcacert_get_tbs, good)
{
    int ret = 0;
    const uint8_t* tbs = NULL;
    size_t tbs_size = 0;

    ret = atcacert_get_tbs(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, &tbs, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(&g_cert_def_cert_template[g_cert_def.tbs_cert_loc.offset], tbs);
    TEST_ASSERT_EQUAL(g_cert_def.tbs_cert_loc.count, tbs_size);
}

TEST(atcacert_get_tbs, bad_cert)
{
    int ret = 0;
    const uint8_t* tbs = NULL;
    size_t tbs_size = 0;

    g_cert_def.tbs_cert_loc.count = g_cert_def.cert_template_size - g_cert_def.tbs_cert_loc.offset + 1;

    ret = atcacert_get_tbs(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, &tbs, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_CERT, ret);
}

TEST(atcacert_get_tbs, bad_params)
{
    int ret = 0;
    const uint8_t* tbs = NULL;
    size_t tbs_size = 0;

    ret = atcacert_get_tbs(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, &tbs, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(&g_cert_def, NULL, g_cert_def.cert_template_size, &tbs, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(NULL, NULL, g_cert_def.cert_template_size, &tbs, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(NULL, NULL, g_cert_def.cert_template_size, NULL, &tbs_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, &tbs, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, &tbs, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(&g_cert_def, NULL, g_cert_def.cert_template_size, &tbs, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(NULL, NULL, g_cert_def.cert_template_size, &tbs, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs(NULL, NULL, g_cert_def.cert_template_size, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_tbs_digest);

TEST_SETUP(atcacert_get_tbs_digest)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_tbs_digest)
{
}

TEST(atcacert_get_tbs_digest, good)
{
    int ret = 0;
    uint8_t tbs_digest[32];
    static const uint8_t tbs_digest_ref[32] = {
        0x05, 0x5E, 0x43, 0x72, 0x93, 0xD4, 0xE1, 0x74, 0xF7, 0x14, 0x9D, 0x6A, 0xA6, 0x6E, 0xEA, 0xC5,
        0xB1, 0xD7, 0x8E, 0x24, 0x01, 0x29, 0x5C, 0xF8, 0x81, 0xC2, 0xAE, 0x85, 0x1F, 0xD1, 0xF6, 0x8B
    };

    ret = atcacert_get_tbs_digest(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, tbs_digest);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(tbs_digest_ref, tbs_digest, sizeof(tbs_digest_ref));
}

TEST(atcacert_get_tbs_digest, bad_params)
{
    int ret = 0;
    uint8_t tbs_digest[32];

    ret = atcacert_get_tbs_digest(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, tbs_digest);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs_digest(&g_cert_def, NULL, g_cert_def.cert_template_size, tbs_digest);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs_digest(NULL, NULL, g_cert_def.cert_template_size, tbs_digest);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs_digest(&g_cert_def, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs_digest(NULL, g_cert_def_cert_template, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs_digest(&g_cert_def, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_tbs_digest(NULL, NULL, g_cert_def.cert_template_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_merge_device_loc);

TEST_SETUP(atcacert_merge_device_loc)
{
}

TEST_TEAR_DOWN(atcacert_merge_device_loc)
{
}

TEST(atcacert_merge_device_loc, empty_list)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 2,
        .is_genkey  = FALSE,
        .offset     = 16,
        .count      = 32
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&new_device_loc, &device_locs[0], sizeof(device_locs[0]));
}

TEST(atcacert_merge_device_loc, devzone_none)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_NONE,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(0, device_locs_count);
}

TEST(atcacert_merge_device_loc, count0)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 0
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(0, device_locs_count);
}

// 0          16 32         40
// |---new---|
//               |---cur---|
TEST(atcacert_merge_device_loc, align1)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 32,
        .count      = 40 - 32
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 32,
            .count = 40 - 32
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 16 - 0
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(2, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 0         16         24
// |---new---|
//           |---cur---|
TEST(atcacert_merge_device_loc, align2)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 16,
        .count      = 24 - 16
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 24 - 0
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 0      14  16     22
// |---new---|
//        |---cur---|
TEST(atcacert_merge_device_loc, align3)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 14,
        .count      = 22 - 14
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 22 - 0
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 16         45
// |---new---|
// |---cur---|
TEST(atcacert_merge_device_loc, align4)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 16,
        .count      = 45 - 16
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 16,
        .count      = 45 - 16
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 16,
            .count = 45 - 16
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 0  8          9  20
// |------new------|
//    |---cur---|
TEST(atcacert_merge_device_loc, align5)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 8,
        .count      = 9 - 8
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 20 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 20 - 0
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 0  8          9  20
//    |---new---|
// |------cur------|
TEST(atcacert_merge_device_loc, align6)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 20 - 0
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 9,
        .count      = 9 - 8
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 20 - 0
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 5     10        567
//       |---new---|
// |------cur------|
TEST(atcacert_merge_device_loc, align7)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 5,
        .count      = 567 - 5
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 567 - 10
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 5,
            .count = 567 - 5
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 5     10        567
// |------new------|
//       |---cur---|
TEST(atcacert_merge_device_loc, align8)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 567 - 10
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 5,
        .count      = 567 - 5
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 5,
            .count = 567 - 5
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 8      10 12     15
//        |---new---|
// |---cur---|
TEST(atcacert_merge_device_loc, align9)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 8,
        .count      = 12 - 8
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 15 - 10
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 8,
            .count = 15 - 8
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 1         15        1000
//           |---new---|
// |---cur---|
TEST(atcacert_merge_device_loc, align10)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 1,
        .count      = 15 - 1
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 15,
        .count      = 1000 - 15
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 1,
            .count = 1000 - 1
        },
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

// 8          9 50         100
//              |---new---|
// |---cur---|
TEST(atcacert_merge_device_loc, align11)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 8,
        .count      = 9 - 8
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 50,
        .count      = 100 - 50
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 8,
            .count = 9 - 8
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 50,
            .count = 100 - 50
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(2, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

TEST(atcacert_merge_device_loc, 32block_no_change)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 32,
        .count      = 64
    };
    static const atcacert_device_loc_t ref_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 32,
        .count      = 64
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_loc, &device_locs[0], sizeof(device_locs[0]));
}

TEST(atcacert_merge_device_loc, 32block_round_down)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 2,
        .is_genkey  = FALSE,
        .offset     = 1,
        .count      = 31
    };
    const atcacert_device_loc_t ref_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 2,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 32
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_loc, &device_locs[0], sizeof(device_locs[0]));
}

TEST(atcacert_merge_device_loc, 32block_round_up)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 63
    };
    static const atcacert_device_loc_t ref_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 64
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_loc, &device_locs[0], sizeof(device_locs[0]));
}

TEST(atcacert_merge_device_loc, 32block_round_both)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 33,
        .count      = 62
    };
    static const atcacert_device_loc_t ref_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 32,
        .count      = 64
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_loc, &device_locs[0], sizeof(device_locs[0]));
}

TEST(atcacert_merge_device_loc, 32block_round_down_merge)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[1] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 8,
            .is_genkey = FALSE,
            .offset = 64,
            .count = 32
        }
    };
    size_t device_locs_count = 1;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 100,
        .count      = 60
    };
    static const atcacert_device_loc_t ref_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 64,
        .count      = 96
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_loc, &device_locs[0], sizeof(device_locs[0]));
}

TEST(atcacert_merge_device_loc, 32block_round_up_merge)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[1] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 8,
            .is_genkey = FALSE,
            .offset = 64,
            .count = 32
        }
    };
    size_t device_locs_count = 1;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 60
    };
    static const atcacert_device_loc_t ref_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 96
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_loc, &device_locs[0], sizeof(device_locs[0]));
}

TEST(atcacert_merge_device_loc, data_diff_slot)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 14,
        .count      = 22 - 14
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 1,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 14,
            .count = 22 - 14
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 1,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 16 - 0
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(2, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

TEST(atcacert_merge_device_loc, data_diff_genkey)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 14,
        .count      = 22 - 14
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 16 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 14,
            .count = 22 - 14
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 16 - 0
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(2, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

TEST(atcacert_merge_device_loc, config)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_CONFIG,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 14,
        .count      = 22 - 14
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_CONFIG,
        .slot       = 1,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 16 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_CONFIG,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 22 - 0
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}


TEST(atcacert_merge_device_loc, otp)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t device_loc_cur = {
        .zone       = DEVZONE_OTP,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 14,
        .count      = 22 - 14
    };
    static const atcacert_device_loc_t device_loc_new = {
        .zone       = DEVZONE_OTP,
        .slot       = 1,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 16 - 0
    };
    static const atcacert_device_loc_t device_locs_ref[] = {
        {
            .zone = DEVZONE_OTP,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 22 - 0
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_cur,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&device_loc_cur, device_locs, sizeof(device_locs[0]) * device_locs_count);

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &device_loc_new,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(1, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(device_locs_ref, device_locs, sizeof(device_locs[0]) * device_locs_count);
}

TEST(atcacert_merge_device_loc, first)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[5] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        }
    };
    size_t device_locs_count = 4;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 72
    };
    static const atcacert_device_loc_t ref_device_locs[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(ref_device_locs) / sizeof(ref_device_locs[0]), device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], sizeof(ref_device_locs));
}

TEST(atcacert_merge_device_loc, mid)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[5] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        }
    };
    size_t device_locs_count = 4;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 11,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 300
    };
    static const atcacert_device_loc_t ref_device_locs[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 310
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(ref_device_locs) / sizeof(ref_device_locs[0]), device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], sizeof(ref_device_locs));
}

TEST(atcacert_merge_device_loc, last)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[5] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        }
    };
    size_t device_locs_count = 4;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 12,
        .is_genkey  = FALSE,
        .offset     = 72,
        .count      = 1
    };
    static const atcacert_device_loc_t ref_device_locs[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 73
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(ref_device_locs) / sizeof(ref_device_locs[0]), device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], sizeof(ref_device_locs));
}

TEST(atcacert_merge_device_loc, add)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[5] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        }
    };
    size_t device_locs_count = 4;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_CONFIG,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16
    };
    static const atcacert_device_loc_t ref_device_locs[] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_CONFIG,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 16
        }
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(ref_device_locs) / sizeof(ref_device_locs[0]), device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], sizeof(ref_device_locs));
}

TEST(atcacert_merge_device_loc, small_buf)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[4] = {
        {
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = TRUE,
            .offset = 0,
            .count = 64
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        },
        {
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 72
        }
    };
    size_t device_locs_count = 4;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_CONFIG,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16
    };

    ret = atcacert_merge_device_loc(
        device_locs,
        &device_locs_count,
        device_locs_max_count,
        &new_device_loc,
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BUFFER_TOO_SMALL, ret);
}

TEST(atcacert_merge_device_loc, bad_params)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[4];
    size_t device_locs_count = 4;
    size_t device_locs_max_count = sizeof(device_locs) / sizeof(device_locs[0]);
    static const atcacert_device_loc_t new_device_loc = {
        .zone       = DEVZONE_CONFIG,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 16
    };

    ret = atcacert_merge_device_loc(NULL, &device_locs_count, device_locs_max_count, &new_device_loc, 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(device_locs, NULL, device_locs_max_count, &new_device_loc, 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(NULL, NULL, device_locs_max_count, &new_device_loc, 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(device_locs, &device_locs_count, device_locs_max_count, NULL, 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(NULL, &device_locs_count, device_locs_max_count, NULL, 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(device_locs, NULL, device_locs_max_count, NULL, 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(NULL, NULL, device_locs_max_count, NULL, 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(device_locs, &device_locs_count, device_locs_max_count, &new_device_loc, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(NULL, &device_locs_count, device_locs_max_count, &new_device_loc, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(device_locs, NULL, device_locs_max_count, &new_device_loc, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(NULL, NULL, device_locs_max_count, &new_device_loc, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(device_locs, &device_locs_count, device_locs_max_count, NULL, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(NULL, &device_locs_count, device_locs_max_count, NULL, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(device_locs, NULL, device_locs_max_count, NULL, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_merge_device_loc(NULL, NULL, device_locs_max_count, NULL, 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_get_device_locs);

TEST_SETUP(atcacert_get_device_locs)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_device_locs)
{
}

TEST(atcacert_get_device_locs, device)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    static const atcacert_device_loc_t cert_sn_dev_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 67
    };
    atcacert_cert_element_t cert_elements[] = {
        {
            .id = "Extra element 1",
            .device_loc ={
                .zone       = DEVZONE_OTP,
                .slot       = 0,
                .is_genkey  = FALSE,
                .offset     = 10,
                .count      = 100
            },
            .cert_loc ={
                .offset = 0,
                .count  = 0
            }
        },
        {
            .id = "Extra element 2",
            .device_loc ={
                .zone       = DEVZONE_DATA,
                .slot       = 15,
                .is_genkey  = FALSE,
                .offset     = 0,
                .count      = 45
            },
            .cert_loc ={
                .offset = 0,
                .count  = 0
            }
        }
    };
    static const atcacert_device_loc_t ref_device_locs[] = {
        {   //compressed cert
            .zone      = DEVZONE_DATA,
            .slot      = 10,
            .is_genkey = 0,
            .offset    = 0,
            .count     = 72
        },
        {   //device serial number
            .zone      = DEVZONE_DATA,
            .slot      = 8,
            .is_genkey = FALSE,
            .offset    = 0,
            .count     = 67
        },
        {   //public key
            .zone      = DEVZONE_DATA,
            .slot      = 0,
            .is_genkey = 1,
            .offset    = 0,
            .count     = 64
        },
        {
            .zone      = DEVZONE_OTP,
            .slot      = 0,
            .is_genkey = FALSE,
            .offset    = 10,
            .count     = 100
        },
        {
            .zone      = DEVZONE_DATA,
            .slot      = 15,
            .is_genkey = FALSE,
            .offset    = 0,
            .count     = 45
        },
        {
            .zone      = DEVZONE_CONFIG,
            .slot      = 0,
            .is_genkey = FALSE,
            .offset    = 0,
            .count     = 13
        },
    };

    useCert(&g_test_cert_def_0_device);

    g_cert_def.cert_sn_dev_loc = cert_sn_dev_loc;

    g_cert_def.cert_elements       = cert_elements;
    g_cert_def.cert_elements_count = sizeof(cert_elements) / sizeof(cert_elements[0]);

    ret = atcacert_get_device_locs(
        &g_cert_def,
        device_locs,
        &device_locs_count,
        sizeof(device_locs) / sizeof(device_locs[0]),
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(ref_device_locs) / sizeof(ref_device_locs[0]), device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], sizeof(ref_device_locs));
}

TEST(atcacert_get_device_locs, signer_device)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    static const atcacert_device_loc_t cert_sn_dev_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 67
    };
    atcacert_cert_element_t cert_elements[] = {
        {
            .id = "Extra element 1",
            .device_loc ={
                .zone       = DEVZONE_OTP,
                .slot       = 0,
                .is_genkey  = FALSE,
                .offset     = 10,
                .count      = 100
            },
            .cert_loc ={
                .offset = 0,
                .count  = 0
            }
        },
        {
            .id = "Extra element 2",
            .device_loc ={
                .zone       = DEVZONE_DATA,
                .slot       = 15,
                .is_genkey  = FALSE,
                .offset     = 0,
                .count      = 45
            },
            .cert_loc ={
                .offset = 0,
                .count  = 0
            }
        }
    };
    static const atcacert_device_loc_t ref_device_locs[] = {
        {
            //signer compressed cert loc
            .zone = DEVZONE_DATA,
            .slot = 12,
            .is_genkey = 0,
            .offset = 0,
            .count = 72
        },
        {
            //signer serial number loc
            .zone = DEVZONE_DATA,
            .slot = 8,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 67
        },
        {
            //signer public key loc
            .zone = DEVZONE_DATA,
            .slot = 11,
            .is_genkey = 0,
            .offset = 0,
            .count = 72
        },
        {
            //device compressed cert loc
            .zone = DEVZONE_DATA,
            .slot = 10,
            .is_genkey = 0,
            .offset = 0,
            .count = 72
        },
        {
            //device public key loc
            .zone = DEVZONE_DATA,
            .slot = 0,
            .is_genkey = 1,
            .offset = 0,
            .count = 64
        },
        {
            //device extra element 1
            .zone = DEVZONE_OTP,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 10,
            .count = 100
        },
        {
            //device extra element 2
            .zone = DEVZONE_DATA,
            .slot = 15,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 45
        },
        {
            //device serial number loc (in device config)
            .zone = DEVZONE_CONFIG,
            .slot = 0,
            .is_genkey = FALSE,
            .offset = 0,
            .count = 13
        },
    };

    g_cert_def.cert_sn_dev_loc = cert_sn_dev_loc;

    ret = atcacert_get_device_locs(
        &g_cert_def,
        device_locs,
        &device_locs_count,
        sizeof(device_locs) / sizeof(device_locs[0]),
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(3, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], device_locs_count * sizeof(ref_device_locs[0]));

    useCert(&g_test_cert_def_0_device);

    g_cert_def.cert_sn_dev_loc = cert_sn_dev_loc;

    g_cert_def.cert_elements = cert_elements;
    g_cert_def.cert_elements_count = sizeof(cert_elements) / sizeof(cert_elements[0]);

    ret = atcacert_get_device_locs(
        &g_cert_def,
        device_locs,
        &device_locs_count,
        sizeof(device_locs) / sizeof(device_locs[0]),
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(ref_device_locs) / sizeof(ref_device_locs[0]), device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], sizeof(ref_device_locs));
}

TEST(atcacert_get_device_locs, 32block_signer_device)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[16];
    size_t device_locs_count = 0;
    static const atcacert_device_loc_t cert_sn_dev_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 67
    };
    atcacert_cert_element_t cert_elements[] = {
        {
            .id = "Extra element 1",
            .device_loc ={
                .zone       = DEVZONE_OTP,
                .slot       = 0,
                .is_genkey  = FALSE,
                .offset     = 10,
                .count      = 100
            },
            .cert_loc ={
                .offset = 0,
                .count  = 0
            }
        },
        {
            .id = "Extra element 2",
            .device_loc ={
                .zone       = DEVZONE_DATA,
                .slot       = 15,
                .is_genkey  = FALSE,
                .offset     = 0,
                .count      = 45
            },
            .cert_loc ={
                .offset = 0,
                .count  = 0
            }
        }
    };
    static const atcacert_device_loc_t ref_device_locs[] = {
        {   //
            .zone      = DEVZONE_DATA,
            .slot      = 12,
            .is_genkey = 0,
            .offset    = 0,
            .count     = 96
        },
        {
            .zone      = DEVZONE_DATA,
            .slot      = 8,
            .is_genkey = FALSE,
            .offset    = 0,
            .count     = 96
        },
        {
            .zone      = DEVZONE_DATA,
            .slot      = 11,
            .is_genkey = 0,
            .offset    = 0,
            .count     = 96
        },
        {
            .zone      = DEVZONE_DATA,
            .slot      = 10,
            .is_genkey = 0,
            .offset    = 0,
            .count     = 96
        },
        {
            .zone      = DEVZONE_DATA,
            .slot      = 0,
            .is_genkey = 1,
            .offset    = 0,
            .count     = 64
        },
        {
            .zone      = DEVZONE_OTP,
            .slot      = 0,
            .is_genkey = FALSE,
            .offset    = 0,
            .count     = 128
        },
        {
            .zone      = DEVZONE_DATA,
            .slot      = 15,
            .is_genkey = FALSE,
            .offset    = 0,
            .count     = 64
        },
        {
            .zone      = DEVZONE_CONFIG,
            .slot      = 0,
            .is_genkey = FALSE,
            .offset    = 0,
            .count     = 32
        },
    };

    g_cert_def.cert_sn_dev_loc = cert_sn_dev_loc;

    ret = atcacert_get_device_locs(
        &g_cert_def,
        device_locs,
        &device_locs_count,
        sizeof(device_locs) / sizeof(device_locs[0]),
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(3, device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], device_locs_count * sizeof(ref_device_locs[0]));

    useCert(&g_test_cert_def_0_device);

    g_cert_def.cert_sn_dev_loc = cert_sn_dev_loc;

    g_cert_def.cert_elements = cert_elements;
    g_cert_def.cert_elements_count = sizeof(cert_elements) / sizeof(cert_elements[0]);

    ret = atcacert_get_device_locs(
        &g_cert_def,
        device_locs,
        &device_locs_count,
        sizeof(device_locs) / sizeof(device_locs[0]),
        32);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(ref_device_locs) / sizeof(ref_device_locs[0]), device_locs_count);
    TEST_ASSERT_EQUAL_MEMORY(&ref_device_locs[0], &device_locs[0], sizeof(ref_device_locs));
}

TEST(atcacert_get_device_locs, small_buf)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[2];
    size_t device_locs_count = 0;
    static const atcacert_device_loc_t cert_sn_dev_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 8,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 67
    };

    g_cert_def.cert_sn_dev_loc = cert_sn_dev_loc;

    ret = atcacert_get_device_locs(
        &g_cert_def,
        device_locs,
        &device_locs_count,
        sizeof(device_locs) / sizeof(device_locs[0]),
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BUFFER_TOO_SMALL, ret);
}

TEST(atcacert_get_device_locs, bad_params)
{
    int ret = 0;
    atcacert_device_loc_t device_locs[5];
    size_t device_locs_count = 0;

    ret = atcacert_get_device_locs(NULL, device_locs, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(&g_cert_def, NULL, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(NULL, NULL, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(&g_cert_def, device_locs, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(NULL, device_locs, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(&g_cert_def, NULL, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(NULL, NULL, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 1);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(&g_cert_def, device_locs, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(NULL, device_locs, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(&g_cert_def, NULL, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(NULL, NULL, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(&g_cert_def, device_locs, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(NULL, device_locs, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(&g_cert_def, NULL, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_get_device_locs(NULL, NULL, NULL, sizeof(device_locs) / sizeof(device_locs[0]), 0);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_cert_build);

TEST_SETUP(atcacert_cert_build)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_cert_build)
{
}

TEST(atcacert_cert_build, start_signer)
{
    int ret = 0;
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01, 0x57, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70,
        0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x45, 0x78, 0x61,
        0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x30, 0x3a, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
        0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0c, 0x1d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
        0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf8, 0x0d, 0x8b,
        0x65, 0xe8, 0xbc, 0xce, 0x14, 0x76, 0xe1, 0x8d, 0x05, 0xe2, 0x01, 0x69, 0x3b, 0xa2, 0xa6, 0x59,
        0xcf, 0xb9, 0xfd, 0x95, 0xe7, 0xba, 0xd0, 0x21, 0x77, 0xf1, 0x38, 0x76, 0x1b, 0x34, 0xf1, 0xb3,
        0x58, 0x95, 0xa1, 0x35, 0x0d, 0x94, 0x82, 0x47, 0xe5, 0x23, 0x6f, 0xb3, 0x92, 0x01, 0x51, 0xd1,
        0x3a, 0x6f, 0x01, 0x23, 0xd6, 0x70, 0xb5, 0xe5, 0x0c, 0xe0, 0xff, 0x49, 0x31, 0xa3, 0x50, 0x30,
        0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
        0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1f, 0xaf, 0x8f, 0x90, 0x86, 0x5f,
        0x7d, 0xd2, 0x26, 0xb0, 0x6f, 0xe3, 0x20, 0x4e, 0x48, 0xa5, 0xd2, 0x94, 0x65, 0xe2, 0x30, 0x1f,
        0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4f, 0xaa, 0x04, 0x1c, 0xbc,
        0x8d, 0xa5, 0xdf, 0xe2, 0x47, 0x72, 0x42, 0xbb, 0xb9, 0x5b, 0x51, 0x81, 0x19, 0x27, 0x6d, 0x30,
        0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xcd, 0x89, 0xe0, 0x75, 0xd0, 0x45, 0x93, 0x7b, 0x37, 0x3f, 0x52, 0x6f,
        0xf6, 0x5c, 0x4b, 0x4c, 0xca, 0x7c, 0x61, 0x3c, 0x5f, 0x9c, 0xf2, 0xf4, 0xc9, 0xe7, 0xce, 0xdf,
        0x24, 0xaa, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xf3, 0xc3, 0x7c, 0xd7, 0x9d, 0x5c, 0x43, 0xf4,
        0xa9, 0x1b, 0xb3, 0xb1, 0xc7, 0x3e, 0xb2, 0x66, 0x74, 0x6c, 0x20, 0x53, 0x0a, 0x3b, 0x90, 0x77,
        0x6c, 0xa9, 0xc7, 0x79, 0x0d
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    const atcacert_build_state_t build_state_ref = {
        .cert_def       = &g_cert_def,
        .cert           = cert,
        .cert_size      = &cert_size,
        .max_cert_size  = cert_size,
        .is_device_sn   = FALSE,
        .device_sn      = { 0x00,     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
    };
    atcacert_build_state_t build_state;

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(&build_state_ref, &build_state, sizeof(build_state));
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

static const uint8_t g_padded_public_key[72] = {
    0x00, 0x00, 0x00, 0x00, 0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2,
    0x50, 0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5,
    0xFC, 0x53, 0xF1, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5,
    0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71,
    0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E
};

TEST(atcacert_cert_build, process_signer_public_key)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 11,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01, 0x57, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70,
        0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x45, 0x78, 0x61,
        0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x30, 0x3a, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
        0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0c, 0x1d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
        0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x9f, 0x61, 0xeb,
        0xa0, 0xd7, 0x9e, 0xf2, 0xc4, 0x96, 0xf1, 0x32, 0xf2, 0x50, 0x29, 0x01, 0xef, 0xd1, 0xe8, 0x6d,
        0x45, 0x1a, 0xac, 0x59, 0x70, 0xbe, 0x62, 0xf3, 0xe5, 0xfc, 0x53, 0xf1, 0xd9, 0x20, 0x2d, 0x21,
        0x9b, 0x3b, 0x66, 0x53, 0xc5, 0x5f, 0xd8, 0x1f, 0xaa, 0x99, 0x8c, 0x1f, 0x6c, 0x42, 0x14, 0x2c,
        0x61, 0xb2, 0x83, 0x9e, 0x71, 0x40, 0x06, 0xf2, 0x52, 0x7c, 0xfe, 0xa2, 0x3e, 0xa3, 0x50, 0x30,
        0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
        0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x84, 0x93, 0xb4, 0xc8, 0x5c, 0x54,
        0x69, 0x0c, 0xec, 0xa0, 0x42, 0x41, 0x0c, 0x90, 0xe9, 0x71, 0x98, 0x66, 0xdc, 0x48, 0x30, 0x1f,
        0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4f, 0xaa, 0x04, 0x1c, 0xbc,
        0x8d, 0xa5, 0xdf, 0xe2, 0x47, 0x72, 0x42, 0xbb, 0xb9, 0x5b, 0x51, 0x81, 0x19, 0x27, 0x6d, 0x30,
        0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xcd, 0x89, 0xe0, 0x75, 0xd0, 0x45, 0x93, 0x7b, 0x37, 0x3f, 0x52, 0x6f,
        0xf6, 0x5c, 0x4b, 0x4c, 0xca, 0x7c, 0x61, 0x3c, 0x5f, 0x9c, 0xf2, 0xf4, 0xc9, 0xe7, 0xce, 0xdf,
        0x24, 0xaa, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xf3, 0xc3, 0x7c, 0xd7, 0x9d, 0x5c, 0x43, 0xf4,
        0xa9, 0x1b, 0xb3, 0xb1, 0xc7, 0x3e, 0xb2, 0x66, 0x74, 0x6c, 0x20, 0x53, 0x0a, 0x3b, 0x90, 0x77,
        0x6c, 0xa9, 0xc7, 0x79, 0x0d
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_public_key, g_padded_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, process_signer_comp_cert)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 11,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const atcacert_device_loc_t device_loc_comp_cert = {
        .zone       = DEVZONE_DATA,
        .slot       = 12,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37,
        0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x34, 0x39, 0x30, 0x33, 0x30, 0x37, 0x31,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34,
        0x38, 0x42, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x9F, 0x61, 0xEB,
        0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D,
        0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9, 0x20, 0x2D, 0x21,
        0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C,
        0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x84, 0x93, 0xB4, 0xC8, 0x5C, 0x54,
        0x69, 0x0C, 0xEC, 0xA0, 0x42, 0x41, 0x0C, 0x90, 0xE9, 0x71, 0x98, 0x66, 0xDC, 0x48, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4F, 0xAA, 0x04, 0x1C, 0xBC,
        0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42, 0xBB, 0xB9, 0x5B, 0x51, 0x81, 0x19, 0x27, 0x6D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7,
        0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48,
        0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_public_key, g_padded_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_comp_cert, g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, finish_signer)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 11,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const atcacert_device_loc_t device_loc_comp_cert = {
        .zone       = DEVZONE_DATA,
        .slot       = 12,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0xC4, 0x8B, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37,
        0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x34, 0x39, 0x30, 0x33, 0x30, 0x37, 0x31,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34,
        0x38, 0x42, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x9F, 0x61, 0xEB,
        0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D,
        0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9, 0x20, 0x2D, 0x21,
        0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C,
        0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x84, 0x93, 0xB4, 0xC8, 0x5C, 0x54,
        0x69, 0x0C, 0xEC, 0xA0, 0x42, 0x41, 0x0C, 0x90, 0xE9, 0x71, 0x98, 0x66, 0xDC, 0x48, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4F, 0xAA, 0x04, 0x1C, 0xBC,
        0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42, 0xBB, 0xB9, 0x5B, 0x51, 0x81, 0x19, 0x27, 0x6D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7,
        0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48,
        0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_public_key, g_padded_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_comp_cert, g_comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_finish(&build_state);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}


static atcacert_cert_element_t g_auth_key_cert_element = {
    "authKeyId",
    {
        .zone = DEVZONE_DATA,
        .slot = 15,
        .is_genkey = FALSE,
        .offset = 0,
        .count = 20
    },
    {
        .offset = 331,
        .count = 20
    },
    {
        TF_NONE,
        TF_NONE
    }
};

TEST(atcacert_cert_build, start_signer_no_ca_key)
{
    int ret = 0;
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01, 0x57, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70,
        0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x45, 0x78, 0x61,
        0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x30, 0x3a, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
        0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0c, 0x1d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
        0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf8, 0x0d, 0x8b,
        0x65, 0xe8, 0xbc, 0xce, 0x14, 0x76, 0xe1, 0x8d, 0x05, 0xe2, 0x01, 0x69, 0x3b, 0xa2, 0xa6, 0x59,
        0xcf, 0xb9, 0xfd, 0x95, 0xe7, 0xba, 0xd0, 0x21, 0x77, 0xf1, 0x38, 0x76, 0x1b, 0x34, 0xf1, 0xb3,
        0x58, 0x95, 0xa1, 0x35, 0x0d, 0x94, 0x82, 0x47, 0xe5, 0x23, 0x6f, 0xb3, 0x92, 0x01, 0x51, 0xd1,
        0x3a, 0x6f, 0x01, 0x23, 0xd6, 0x70, 0xb5, 0xe5, 0x0c, 0xe0, 0xff, 0x49, 0x31, 0xa3, 0x50, 0x30,
        0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
        0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1f, 0xaf, 0x8f, 0x90, 0x86, 0x5f,
        0x7d, 0xd2, 0x26, 0xb0, 0x6f, 0xe3, 0x20, 0x4e, 0x48, 0xa5, 0xd2, 0x94, 0x65, 0xe2, 0x30, 0x1f,
        0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x77, 0x23, 0xa2, 0xc4, 0x32,
        0xa6, 0x94, 0x1d, 0x81, 0x32, 0xcb, 0x76, 0x04, 0xc3, 0x80, 0x1d, 0xd2, 0xbe, 0x95, 0x5d, 0x30,
        0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xcd, 0x89, 0xe0, 0x75, 0xd0, 0x45, 0x93, 0x7b, 0x37, 0x3f, 0x52, 0x6f,
        0xf6, 0x5c, 0x4b, 0x4c, 0xca, 0x7c, 0x61, 0x3c, 0x5f, 0x9c, 0xf2, 0xf4, 0xc9, 0xe7, 0xce, 0xdf,
        0x24, 0xaa, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xf3, 0xc3, 0x7c, 0xd7, 0x9d, 0x5c, 0x43, 0xf4,
        0xa9, 0x1b, 0xb3, 0xb1, 0xc7, 0x3e, 0xb2, 0x66, 0x74, 0x6c, 0x20, 0x53, 0x0a, 0x3b, 0x90, 0x77,
        0x6c, 0xa9, 0xc7, 0x79, 0x0d
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    const atcacert_build_state_t build_state_ref = {
        .cert_def      = &g_cert_def,
        .cert          = cert,
        .cert_size     = &cert_size,
        .max_cert_size = cert_size,
        .is_device_sn  = FALSE,
        .device_sn     = { 0x00,     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
    };
    atcacert_build_state_t build_state;

    g_auth_key_cert_element.cert_loc = g_cert_def.std_cert_elements[STDCERT_AUTH_KEY_ID];
    g_cert_def.cert_elements = &g_auth_key_cert_element;
    g_cert_def.cert_elements_count = 1;

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(&build_state_ref, &build_state, sizeof(build_state));
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, process_signer_auth_key_id)
{
    int ret = 0;
    static const uint8_t auth_key_id[20] = {
        0x4F, 0xAA, 0x04, 0x1C, 0xBC, 0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42, 0xBB, 0xB9, 0x5B, 0x51,
        0x81, 0x19, 0x27, 0x6D
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01, 0x57, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70,
        0x6c, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x45, 0x78, 0x61,
        0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31,
        0x30, 0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30,
        0x30, 0x31, 0x32, 0x31, 0x35, 0x5a, 0x30, 0x3a, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
        0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0c, 0x1d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x58, 0x58,
        0x58, 0x58, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
        0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf8, 0x0d, 0x8b,
        0x65, 0xe8, 0xbc, 0xce, 0x14, 0x76, 0xe1, 0x8d, 0x05, 0xe2, 0x01, 0x69, 0x3b, 0xa2, 0xa6, 0x59,
        0xcf, 0xb9, 0xfd, 0x95, 0xe7, 0xba, 0xd0, 0x21, 0x77, 0xf1, 0x38, 0x76, 0x1b, 0x34, 0xf1, 0xb3,
        0x58, 0x95, 0xa1, 0x35, 0x0d, 0x94, 0x82, 0x47, 0xe5, 0x23, 0x6f, 0xb3, 0x92, 0x01, 0x51, 0xd1,
        0x3a, 0x6f, 0x01, 0x23, 0xd6, 0x70, 0xb5, 0xe5, 0x0c, 0xe0, 0xff, 0x49, 0x31, 0xa3, 0x50, 0x30,
        0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
        0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1f, 0xaf, 0x8f, 0x90, 0x86, 0x5f,
        0x7d, 0xd2, 0x26, 0xb0, 0x6f, 0xe3, 0x20, 0x4e, 0x48, 0xa5, 0xd2, 0x94, 0x65, 0xe2, 0x30, 0x1f,
        0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4f, 0xaa, 0x04, 0x1c, 0xbc,
        0x8d, 0xa5, 0xdf, 0xe2, 0x47, 0x72, 0x42, 0xbb, 0xb9, 0x5b, 0x51, 0x81, 0x19, 0x27, 0x6d, 0x30,
        0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x43, 0x90, 0xcd, 0x89, 0xe0, 0x75, 0xd0, 0x45, 0x93, 0x7b, 0x37, 0x3f, 0x52, 0x6f,
        0xf6, 0x5c, 0x4b, 0x4c, 0xca, 0x7c, 0x61, 0x3c, 0x5f, 0x9c, 0xf2, 0xf4, 0xc9, 0xe7, 0xce, 0xdf,
        0x24, 0xaa, 0x02, 0x21, 0x00, 0x89, 0x52, 0x36, 0xf3, 0xc3, 0x7c, 0xd7, 0x9d, 0x5c, 0x43, 0xf4,
        0xa9, 0x1b, 0xb3, 0xb1, 0xc7, 0x3e, 0xb2, 0x66, 0x74, 0x6c, 0x20, 0x53, 0x0a, 0x3b, 0x90, 0x77,
        0x6c, 0xa9, 0xc7, 0x79, 0x0d
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    const atcacert_build_state_t build_state_ref = {
        .cert_def      = &g_cert_def,
        .cert          = cert,
        .cert_size     = &cert_size,
        .max_cert_size = cert_size,
        .is_device_sn  = FALSE,
        .device_sn     = { 0x00,     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
    };
    atcacert_build_state_t build_state;

    g_auth_key_cert_element.cert_loc = g_cert_def.std_cert_elements[STDCERT_AUTH_KEY_ID];
    g_cert_def.cert_elements = &g_auth_key_cert_element;
    g_cert_def.cert_elements_count = 1;

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &g_auth_key_cert_element.device_loc, auth_key_id);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    TEST_ASSERT_EQUAL_MEMORY(&build_state_ref, &build_state, sizeof(build_state));
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, start_device)
{
    int ret = 0;
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0x8a, 0x30, 0x82, 0x01, 0x30, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x40,
        0x01, 0x23, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xee, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
        0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3a, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a,
        0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0c, 0x1d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5a, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78,
        0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18,
        0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
        0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0xc3, 0xdc, 0x86, 0xe9, 0xcc, 0x59, 0xa1, 0xfa, 0xf8, 0xe6, 0x02, 0xb3, 0x44,
        0x89, 0xd1, 0x70, 0x4a, 0x3b, 0x44, 0x04, 0x52, 0xaa, 0x11, 0x93, 0x35, 0xa9, 0xbe, 0x6f, 0x68,
        0x32, 0xdc, 0x59, 0xce, 0x5e, 0x74, 0x73, 0xb8, 0x44, 0xbd, 0x08, 0x4d, 0x5d, 0x3d, 0xe5, 0xde,
        0x21, 0xc3, 0x4f, 0x8d, 0xc1, 0x61, 0x4f, 0x17, 0x27, 0xaf, 0x6d, 0xc4, 0x9c, 0x42, 0x83, 0xee,
        0x36, 0xe2, 0x31, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x4f, 0xaa, 0x04, 0x1c, 0xbc, 0x8d, 0xa5, 0xdf, 0xe2, 0x47, 0x72, 0x42,
        0xbb, 0xb9, 0x5b, 0x51, 0x81, 0x19, 0x27, 0x6d, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
        0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5e, 0x13, 0x59, 0x05, 0x08,
        0xda, 0x03, 0xfd, 0x94, 0x1b, 0xaf, 0xef, 0x8a, 0x3d, 0xc8, 0x24, 0xe5, 0x49, 0x07, 0xb8, 0xa2,
        0xbd, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xe1, 0xaa, 0x02, 0x21, 0x00, 0x96, 0xff,
        0x2b, 0xdf, 0x34, 0x54, 0x9b, 0x7c, 0x56, 0x8f, 0x54, 0x44, 0x4f, 0xe6, 0xad, 0x3b, 0xfe, 0x63,
        0xbd, 0xd2, 0x93, 0x65, 0xf2, 0x65, 0x59, 0x22, 0xc6, 0x25, 0x90, 0x7a, 0xec, 0x19
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    const atcacert_build_state_t build_state_ref = {
        .cert_def       = &g_cert_def,
        .cert           = cert,
        .cert_size      = &cert_size,
        .max_cert_size  = cert_size,
        .is_device_sn   = FALSE,
        .device_sn      = { 0x00,     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
    };
    atcacert_build_state_t build_state;

    useCert(&g_test_cert_def_0_device);

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL_MEMORY(&build_state_ref, &build_state, sizeof(build_state));
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, process_device_public_key)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 64
    };
    static const uint8_t public_key[72] = { // subject public key
        0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF,
        0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9,
        0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C,
        0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0x8a, 0x30, 0x82, 0x01, 0x30, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x40,
        0x01, 0x23, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xee, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
        0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3a, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a,
        0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0c, 0x1d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x58, 0x58, 0x58,
        0x58, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31,
        0x36, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x37, 0x33, 0x31, 0x30, 0x30, 0x31, 0x32, 0x31, 0x36,
        0x5a, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78,
        0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18,
        0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
        0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x9f, 0x61, 0xeb, 0xa0, 0xd7, 0x9e, 0xf2, 0xc4, 0x96, 0xf1, 0x32, 0xf2, 0x50,
        0x29, 0x01, 0xef, 0xd1, 0xe8, 0x6d, 0x45, 0x1a, 0xac, 0x59, 0x70, 0xbe, 0x62, 0xf3, 0xe5, 0xfc,
        0x53, 0xf1, 0xd9, 0x20, 0x2d, 0x21, 0x9b, 0x3b, 0x66, 0x53, 0xc5, 0x5f, 0xd8, 0x1f, 0xaa, 0x99,
        0x8c, 0x1f, 0x6c, 0x42, 0x14, 0x2c, 0x61, 0xb2, 0x83, 0x9e, 0x71, 0x40, 0x06, 0xf2, 0x52, 0x7c,
        0xfe, 0xa2, 0x3e, 0xa3, 0x23, 0x30, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x4f, 0xaa, 0x04, 0x1c, 0xbc, 0x8d, 0xa5, 0xdf, 0xe2, 0x47, 0x72, 0x42,
        0xbb, 0xb9, 0x5b, 0x51, 0x81, 0x19, 0x27, 0x6d, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
        0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5e, 0x13, 0x59, 0x05, 0x08,
        0xda, 0x03, 0xfd, 0x94, 0x1b, 0xaf, 0xef, 0x8a, 0x3d, 0xc8, 0x24, 0xe5, 0x49, 0x07, 0xb8, 0xa2,
        0xbd, 0x36, 0x60, 0x26, 0x14, 0x75, 0x27, 0x36, 0x66, 0xe1, 0xaa, 0x02, 0x21, 0x00, 0x96, 0xff,
        0x2b, 0xdf, 0x34, 0x54, 0x9b, 0x7c, 0x56, 0x8f, 0x54, 0x44, 0x4f, 0xe6, 0xad, 0x3b, 0xfe, 0x63,
        0xbd, 0xd2, 0x93, 0x65, 0xf2, 0x65, 0x59, 0x22, 0xc6, 0x25, 0x90, 0x7a, 0xec, 0x19
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    useCert(&g_test_cert_def_0_device);

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_public_key, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, process_device_comp_cert)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 64
    };
    static const uint8_t public_key[72] = { // subject public key
        0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF,
        0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9,
        0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C,
        0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E
    };
    static const atcacert_device_loc_t device_loc_comp_cert = {
        .zone       = DEVZONE_DATA,
        .slot       = 10,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x00, 0x80, 0x00
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x40,
        0x01, 0x23, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xEE, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34, 0x38,
        0x42, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30,
        0x30, 0x5A, 0x17, 0x0D, 0x34, 0x39, 0x30, 0x33, 0x30, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50,
        0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC,
        0x53, 0xF1, 0xD9, 0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99,
        0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C,
        0xFE, 0xA2, 0x3E, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x4F, 0xAA, 0x04, 0x1C, 0xBC, 0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42,
        0xBB, 0xB9, 0x5B, 0x51, 0x81, 0x19, 0x27, 0x6D, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A,
        0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F, 0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99,
        0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25, 0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12,
        0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7, 0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2,
        0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48, 0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    useCert(&g_test_cert_def_0_device);

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_public_key, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_comp_cert, comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, process_device_comp_cert_new_expire)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 64
    };
    static const uint8_t public_key[72] = { // subject public key
        0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF,
        0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9,
        0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C,
        0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E
    };
    static const atcacert_device_loc_t device_loc_comp_cert = {
        .zone       = DEVZONE_DATA,
        .slot       = 10,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5B, 0xC4, 0x8B, 0x00, 0x80, 0x00
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x40,
        0x01, 0x23, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xEE, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34, 0x38,
        0x42, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30,
        0x30, 0x5A, 0x17, 0x0D, 0x34, 0x38, 0x30, 0x33, 0x30, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50,
        0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC,
        0x53, 0xF1, 0xD9, 0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99,
        0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C,
        0xFE, 0xA2, 0x3E, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x4F, 0xAA, 0x04, 0x1C, 0xBC, 0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42,
        0xBB, 0xB9, 0x5B, 0x51, 0x81, 0x19, 0x27, 0x6D, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A,
        0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F, 0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99,
        0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25, 0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12,
        0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7, 0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2,
        0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48, 0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    useCert(&g_test_cert_def_0_device);

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_public_key, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_comp_cert, comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, finish_device)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = TRUE,
        .offset     = 0,
        .count      = 64
    };
    static const uint8_t public_key[72] = { // subject public key
        0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF,
        0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9,
        0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C,
        0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E
    };
    static const atcacert_device_loc_t device_loc_comp_cert = {
        .zone       = DEVZONE_DATA,
        .slot       = 10,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const uint8_t comp_cert[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x5C, 0xC4, 0x8B, 0x00, 0x80, 0x00
    };
    static const atcacert_device_loc_t device_loc_config = {
        .zone       = DEVZONE_CONFIG,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 32
    };
    static const uint8_t config[32] = {
        0x01, 0x23, 0x12, 0x24, 0x00, 0x00, 0x50, 0x00, 0xD8, 0x2C, 0xA5, 0x71, 0xEE, 0xC0, 0x69, 0x00,
        0xC0, 0x00, 0x55, 0x00, 0x83, 0x20, 0x87, 0x20, 0x8F, 0x20, 0xC4, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F
    };
    static const uint8_t cert_ref[] = {
        0x30, 0x82, 0x01, 0x8A, 0x30, 0x82, 0x01, 0x30, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x40,
        0x01, 0x23, 0x12, 0x24, 0xD8, 0x2C, 0xA5, 0x71, 0xEE, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
        0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
        0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
        0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43,
        0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34, 0x38,
        0x42, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30,
        0x30, 0x5A, 0x17, 0x0D, 0x34, 0x39, 0x30, 0x33, 0x30, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
        0x5A, 0x30, 0x35, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78,
        0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x18,
        0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38,
        0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
        0x42, 0x00, 0x04, 0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50,
        0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC,
        0x53, 0xF1, 0xD9, 0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99,
        0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C,
        0xFE, 0xA2, 0x3E, 0xA3, 0x23, 0x30, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
        0x30, 0x16, 0x80, 0x14, 0x4F, 0xAA, 0x04, 0x1C, 0xBC, 0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42,
        0xBB, 0xB9, 0x5B, 0x51, 0x81, 0x19, 0x27, 0x6D, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
        0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A,
        0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F, 0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99,
        0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25, 0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12,
        0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7, 0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2,
        0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48, 0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    useCert(&g_test_cert_def_0_device);

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_public_key, public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_comp_cert, comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc_config, config);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_finish(&build_state);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}

TEST(atcacert_cert_build, transform)
{
    int ret = 0;
    static const uint8_t public_key[64] = {
        0x86, 0xC1, 0x06, 0xE2, 0x85, 0xCB, 0x97, 0x79, 0x3D, 0x46, 0x11, 0x36,
        0x10, 0xDF, 0xD1, 0xD8, 0xB0, 0x1C, 0x3B, 0xB3, 0x07, 0x95, 0xA7, 0x1F,
        0xD0, 0x16, 0xD3, 0x31, 0x58, 0xC4, 0x4F, 0xA1, 0xC2, 0xAF, 0x35, 0xA7,
        0x49, 0xDE, 0xAE, 0x96, 0xF5, 0xB2, 0xD9, 0x71, 0x57, 0x5E, 0xFF, 0x66,
        0x66, 0x07, 0x6E, 0xEF, 0x58, 0x6E, 0x0A, 0x79, 0x30, 0x24, 0x22, 0xC5,
        0x3B, 0xC9, 0x80, 0xFD
    };

    static const uint8_t comp_cert[72] = {
        0x98, 0x82, 0x05, 0xf4, 0x5b, 0x65, 0x48, 0x3a, 0xf9, 0xea, 0xc4, 0x4e, 0xb0, 0x54, 0x21, 0x7d,
        0x20, 0x84, 0xbe, 0x85, 0xf6, 0xef, 0xd7, 0x5b, 0x9d, 0xa9, 0xdd, 0xdc, 0x4a, 0x09, 0x1d, 0x45,
        0x43, 0xb4, 0xc5, 0x50, 0x88, 0x31, 0xc9, 0x0e, 0x52, 0xd1, 0x50, 0xa1, 0xb2, 0x64, 0xb6, 0x21,
        0xbe, 0x0b, 0xfd, 0xa6, 0xcf, 0x84, 0x26, 0xdf, 0x48, 0xa3, 0x12, 0xaf, 0x29, 0x72, 0x38, 0x0d,
        0x9a, 0x46, 0x6a, 0xca, 0x03, 0x23, 0x80, 0x00
    };

    static const uint8_t slot8[416] = {
        0x32, 0x32, 0x35, 0x34, 0x36, 0x38, 0x36, 0x39, 0x37, 0x33, 0x32, 0x30, 0x36, 0x39, 0x37, 0x33,
        0x32, 0x30, 0x37, 0x37, 0x36, 0x38, 0x36, 0x31, 0x37, 0x34, 0x32, 0x30, 0x36, 0x39, 0x37, 0x33,
        0x32, 0x30, 0x36, 0x33, 0x36, 0x31, 0x36, 0x43, 0x36, 0x43, 0x36, 0x35, 0x36, 0x34, 0x32, 0x30,
        0x36, 0x31, 0x32, 0x30, 0x36, 0x33, 0x37, 0x32, 0x37, 0x39, 0x37, 0x30, 0x37, 0x34, 0x36, 0x46,
        0x36, 0x37, 0x37, 0x32, 0x36, 0x31, 0x36, 0x44, 0x32, 0x43, 0x32, 0x30, 0x36, 0x46, 0x37, 0x32,
        0x32, 0x30, 0x36, 0x33, 0x36, 0x39, 0x37, 0x30, 0x36, 0x38, 0x36, 0x35, 0x37, 0x32, 0x32, 0x43,
        0x32, 0x32, 0x32, 0x30, 0x36, 0x38, 0x36, 0x35, 0x32, 0x30, 0x37, 0x33, 0x36, 0x31, 0x36, 0x39,
        0x36, 0x34, 0x32, 0x63, 0x32, 0x30, 0x32, 0x32, 0x36, 0x39, 0x36, 0x65, 0x32, 0x30, 0x37, 0x37,
        0x36, 0x38, 0x36, 0x39, 0x36, 0x33, 0x36, 0x38, 0x32, 0x30, 0x36, 0x63, 0x36, 0x35, 0x37, 0x34,
        0x37, 0x34, 0x36, 0x35, 0x37, 0x32, 0x37, 0x33, 0x32, 0x30, 0x36, 0x31, 0x37, 0x32, 0x36, 0x35,
        0x32, 0x30, 0x37, 0x30, 0x37, 0x35, 0x37, 0x32, 0x37, 0x30, 0x36, 0x66, 0x37, 0x33, 0x36, 0x35,
        0x36, 0x63, 0x37, 0x39, 0x32, 0x30, 0x37, 0x34, 0x36, 0x38, 0x37, 0x32, 0x36, 0x66, 0x37, 0x37,
        0x36, 0x65, 0x32, 0x30, 0x36, 0x39, 0x36, 0x65, 0x32, 0x30, 0x36, 0x33, 0x36, 0x66, 0x36, 0x65,
        0x36, 0x36, 0x37, 0x35, 0x37, 0x33, 0x36, 0x39, 0x36, 0x66, 0x36, 0x65, 0x32, 0x43, 0x20, 0x32,
        0x30, 0x20, 0x37, 0x37, 0x20, 0x36, 0x38, 0x20, 0x36, 0x39, 0x20, 0x36, 0x33, 0x20, 0x36, 0x38,
        0x20, 0x32, 0x30, 0x20, 0x36, 0x39, 0x20, 0x36, 0x36, 0x20, 0x32, 0x30, 0x20, 0x37, 0x30, 0x20,
        0x37, 0x32, 0x20, 0x36, 0x46, 0x20, 0x37, 0x30, 0x20, 0x36, 0x35, 0x20, 0x37, 0x32, 0x20, 0x36,
        0x43, 0x20, 0x37, 0x39, 0x20, 0x32, 0x30, 0x20, 0x36, 0x31, 0x20, 0x37, 0x32, 0x20, 0x37, 0x32,
        0x20, 0x36, 0x31, 0x20, 0x36, 0x45, 0x20, 0x36, 0x37, 0x20, 0x36, 0x35, 0x20, 0x36, 0x34, 0x32,
        0x30, 0x20, 0x37, 0x37, 0x20, 0x36, 0x66, 0x20, 0x37, 0x35, 0x20, 0x36, 0x63, 0x20, 0x36, 0x34,
        0x20, 0x32, 0x30, 0x20, 0x37, 0x32, 0x20, 0x36, 0x35, 0x20, 0x37, 0x36, 0x20, 0x36, 0x35, 0x20,
        0x36, 0x31, 0x20, 0x36, 0x63, 0x20, 0x32, 0x30, 0x20, 0x37, 0x34, 0x20, 0x36, 0x38, 0x20, 0x36,
        0x35, 0x20, 0x36, 0x39, 0x20, 0x37, 0x32, 0x20, 0x32, 0x30, 0x20, 0x37, 0x33, 0x20, 0x36, 0x35,
        0x20, 0x36, 0x65, 0x20, 0x37, 0x33, 0x20, 0x36, 0x35, 0x20, 0x32, 0x65, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    static const atcacert_device_loc_t slot8_cert_loc = {
        .zone      = DEVZONE_DATA,
        .slot      = 8,
        .is_genkey = false,
        .offset    = 0,
        .count     = sizeof(slot8)
    };

    static const uint8_t config[128] = {
        0x01, 0x23, 0x02, 0x03, 0xed, 0x00, 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0xff, 0x55, 0x01, 0x00,
        0xb0, 0x00, 0x55, 0x00, 0x8f, 0x20, 0xc4, 0x44, 0x87, 0x20, 0x87, 0x20, 0x8f, 0x8f, 0xc4, 0x36,
        0x9f, 0x8f, 0x8f, 0x44, 0x0f, 0x0f, 0xc4, 0x44, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
        0x0f, 0x0f, 0x0f, 0x8f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
        0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x33, 0x00, 0x1c, 0x00, 0x13, 0x00, 0x13, 0x00, 0x5c, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x1c, 0x00,
        0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x10, 0x00
    };
    static const atcacert_device_loc_t config_cert_loc = {
        .zone      = DEVZONE_CONFIG,
        .slot      = 0,
        .is_genkey = false,
        .offset    = 0,
        .count     = sizeof(config)
    };

    static const uint8_t otp[64] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
    };
    static const atcacert_device_loc_t otp_cert_loc = {
        .zone      = DEVZONE_OTP,
        .slot      = 0,
        .is_genkey = false,
        .offset    = 0,
        .count     = sizeof(otp)
    };

    static const uint8_t cert_ref[] = {
        0x86, 0xC1, 0x06, 0xE2, 0x85, 0xCB, 0x97, 0x79, 0x3D, 0x46, 0x11, 0x36, 0x10, 0xDF, 0xD1, 0xD8,
        0xB0, 0x1C, 0x3B, 0xB3, 0x07, 0x95, 0xA7, 0x1F, 0xD0, 0x16, 0xD3, 0x31, 0x58, 0xC4, 0x4F, 0xA1,
        0xC2, 0xAF, 0x35, 0xA7, 0x49, 0xDE, 0xAE, 0x96, 0xF5, 0xB2, 0xD9, 0x71, 0x57, 0x5E, 0xFF, 0x66,
        0x66, 0x07, 0x6E, 0xEF, 0x58, 0x6E, 0x0A, 0x79, 0x30, 0x24, 0x22, 0xC5, 0x3B, 0xC9, 0x80, 0xFD,
        0x43, 0x41, 0x30, 0x33, 0x32, 0x30, 0x31, 0x39, 0x2D, 0x30, 0x34, 0x2D, 0x31, 0x37, 0x54, 0x31,
        0x39, 0x3A, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x5A, 0x32, 0x30, 0x32, 0x39, 0x2D, 0x30, 0x34, 0x2D,
        0x31, 0x37, 0x54, 0x31, 0x39, 0x3A, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x5A, 0x40, 0x01, 0x23, 0x02,
        0x03, 0x04, 0x05, 0x06, 0x07, 0xFF, 0x33, 0x66, 0x20, 0x33, 0x65, 0x20, 0x33, 0x64, 0x20, 0x33,
        0x63, 0x20, 0x33, 0x62, 0x20, 0x33, 0x61, 0x20, 0x33, 0x39, 0x20, 0x33, 0x38, 0x20, 0x33, 0x37,
        0x20, 0x33, 0x36, 0x20, 0x33, 0x35, 0x20, 0x33, 0x34, 0x20, 0x33, 0x33, 0x20, 0x33, 0x32, 0x20,
        0x33, 0x31, 0x20, 0x33, 0x30, 0x20, 0x32, 0x66, 0x20, 0x32, 0x65, 0x20, 0x32, 0x64, 0x20, 0x32,
        0x63, 0x20, 0x32, 0x62, 0x20, 0x32, 0x61, 0x20, 0x32, 0x39, 0x20, 0x32, 0x38, 0x20, 0x32, 0x37,
        0x20, 0x32, 0x36, 0x20, 0x32, 0x35, 0x20, 0x32, 0x34, 0x20, 0x32, 0x33, 0x20, 0x32, 0x32, 0x20,
        0x32, 0x31, 0x20, 0x32, 0x30, 0x20, 0x31, 0x66, 0x20, 0x31, 0x65, 0x20, 0x31, 0x64, 0x20, 0x31,
        0x63, 0x20, 0x31, 0x62, 0x20, 0x31, 0x61, 0x20, 0x31, 0x39, 0x20, 0x31, 0x38, 0x20, 0x31, 0x37,
        0x20, 0x31, 0x36, 0x20, 0x31, 0x35, 0x20, 0x31, 0x34, 0x20, 0x31, 0x33, 0x20, 0x31, 0x32, 0x20,
        0x31, 0x31, 0x20, 0x31, 0x30, 0x20, 0x30, 0x66, 0x20, 0x30, 0x65, 0x20, 0x30, 0x64, 0x20, 0x30,
        0x63, 0x20, 0x30, 0x62, 0x20, 0x30, 0x61, 0x20, 0x30, 0x39, 0x20, 0x30, 0x38, 0x20, 0x30, 0x37,
        0x20, 0x30, 0x36, 0x20, 0x30, 0x35, 0x20, 0x30, 0x34, 0x20, 0x30, 0x33, 0x20, 0x30, 0x32, 0x20,
        0x30, 0x31, 0x20, 0x30, 0x30, 0x30, 0x31, 0x32, 0x33, 0x30, 0x32, 0x30, 0x33, 0x45, 0x44, 0x30,
        0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x46, 0x46, 0x35,
        0x35, 0x30, 0x31, 0x30, 0x30, 0x62, 0x30, 0x30, 0x30, 0x35, 0x35, 0x30, 0x30, 0x38, 0x66, 0x32,
        0x30, 0x63, 0x34, 0x34, 0x34, 0x38, 0x37, 0x32, 0x30, 0x38, 0x37, 0x32, 0x30, 0x38, 0x66, 0x38,
        0x66, 0x63, 0x34, 0x33, 0x36, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x77, 0x68,
        0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6C, 0x6C, 0x65, 0x64, 0x20, 0x61, 0x20, 0x63,
        0x72, 0x79, 0x70, 0x74, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x63, 0x69,
        0x70, 0x68, 0x65, 0x72, 0x2C, 0x22, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2C, 0x20,
        0x22, 0x69, 0x6E, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6C, 0x65, 0x74, 0x74, 0x65, 0x72,
        0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x6C, 0x79, 0x20,
        0x74, 0x68, 0x72, 0x6F, 0x77, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x63, 0x6F, 0x6E, 0x66, 0x75, 0x73,
        0x69, 0x6F, 0x6E, 0x39, 0x46, 0x20, 0x38, 0x46, 0x20, 0x38, 0x46, 0x20, 0x34, 0x34, 0x20, 0x30,
        0x46, 0x20, 0x30, 0x46, 0x20, 0x43, 0x34, 0x20, 0x34, 0x34, 0x20, 0x30, 0x46, 0x20, 0x30, 0x46,
        0x20, 0x30, 0x46, 0x20, 0x30, 0x46, 0x20, 0x30, 0x46, 0x20, 0x30, 0x46, 0x20, 0x30, 0x46, 0x20,
        0x30, 0x46, 0x30, 0x66, 0x20, 0x30, 0x66, 0x20, 0x30, 0x66, 0x20, 0x38, 0x66, 0x20, 0x66, 0x66,
        0x20, 0x66, 0x66, 0x20, 0x66, 0x66, 0x20, 0x66, 0x66, 0x20, 0x30, 0x30, 0x20, 0x30, 0x30, 0x20,
        0x30, 0x30, 0x20, 0x30, 0x30, 0x20, 0x66, 0x66, 0x20, 0x66, 0x66, 0x20, 0x66, 0x66, 0x20, 0x66,
        0x66, 0x2C, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x66, 0x20, 0x70, 0x72, 0x6F, 0x70,
        0x65, 0x72, 0x6C, 0x79, 0x20, 0x61, 0x72, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x64, 0x20, 0x77, 0x6F,
        0x75, 0x6C, 0x64, 0x20, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6C, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
        0x20, 0x73, 0x65, 0x6E, 0x73, 0x65, 0x2E, 0x98, 0x82, 0x05, 0xF4, 0x5B, 0x65, 0x48, 0x3A, 0xF9,
        0xEA, 0xC4, 0x4E, 0xB0, 0x54, 0x21, 0x7D, 0x20, 0x84, 0xBE, 0x85, 0xF6, 0xEF, 0xD7, 0x5B, 0x9D,
        0xA9, 0xDD, 0xDC, 0x4A, 0x09, 0x1D, 0x45, 0x43, 0xB4, 0xC5, 0x50, 0x88, 0x31, 0xC9, 0x0E, 0x52,
        0xD1, 0x50, 0xA1, 0xB2, 0x64, 0xB6, 0x21, 0xBE, 0x0B, 0xFD, 0xA6, 0xCF, 0x84, 0x26, 0xDF, 0x48,
        0xA3, 0x12, 0xAF, 0x29, 0x72, 0x38, 0x0D
    };
    uint8_t cert[sizeof(cert_ref)];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    useCert(&g_test_cert_def_3_device);

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    // Compressed cert
    ret = atcacert_cert_build_process(&build_state, &(build_state.cert_def->comp_cert_dev_loc), comp_cert);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    // Public key
    ret = atcacert_cert_build_process(&build_state, &(build_state.cert_def->public_key_dev_loc), public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    // Add config data
    ret = atcacert_cert_build_process(&build_state, &config_cert_loc, config);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    // Add slot 8 data
    ret = atcacert_cert_build_process(&build_state, &slot8_cert_loc, slot8);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    // Add OTP data
    ret = atcacert_cert_build_process(&build_state, &otp_cert_loc, otp);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_finish(&build_state);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    TEST_ASSERT_EQUAL(sizeof(cert_ref), cert_size);
    TEST_ASSERT_EQUAL_MEMORY(cert_ref, cert, cert_size);
}


TEST(atcacert_cert_build, start_small_buf)
{
    int ret = 0;
    static const uint8_t ca_public_key[64];
    uint8_t cert[512];
    size_t cert_size = g_cert_def.cert_template_size - 1;
    atcacert_build_state_t build_state;

    memset(cert, 0xA5, sizeof(cert));
    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        ca_public_key);
    TEST_ASSERT_EQUAL(cert[cert_size], 0xA5);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

}

TEST(atcacert_cert_build, start_bad_params)
{
    int ret = 0;
    static const uint8_t ca_public_key[64];
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    ret = atcacert_cert_build_start(NULL, &g_cert_def, cert, &cert_size, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, cert, &cert_size, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, cert, &cert_size, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, &g_cert_def, NULL, &cert_size, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, &g_cert_def, NULL, &cert_size, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, NULL, &cert_size, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, NULL, &cert_size, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, &g_cert_def, cert, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, &g_cert_def, cert, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, cert, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, cert, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, &g_cert_def, NULL, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, &g_cert_def, NULL, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, NULL, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, NULL, NULL, ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, &g_cert_def, cert, &cert_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, cert, &cert_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, cert, &cert_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, &g_cert_def, NULL, &cert_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, &g_cert_def, NULL, &cert_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, NULL, &cert_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, NULL, &cert_size, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, &g_cert_def, cert, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, &g_cert_def, cert, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, cert, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, cert, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, &g_cert_def, NULL, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, &g_cert_def, NULL, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(&build_state, NULL, NULL, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_start(NULL, NULL, NULL, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

TEST(atcacert_cert_build, process_bad_params)
{
    int ret = 0;
    static const uint8_t ca_public_key[64];
    static const atcacert_device_loc_t device_loc = {
        .zone       = DEVZONE_DATA,
        .slot       = 11,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    uint8_t device_data[72];
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_process(NULL, &device_loc, device_data);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_process(&build_state, NULL, device_data);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_process(NULL, NULL, device_data);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_process(&build_state, &device_loc, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_process(NULL, &device_loc, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_process(&build_state, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_cert_build_process(NULL, NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

TEST(atcacert_cert_build, finish_missing_device_sn)
{
    int ret = 0;
    uint8_t cert[512];
    size_t cert_size = sizeof(cert);
    atcacert_build_state_t build_state;

    useCert(&g_test_cert_def_0_device);

    ret = atcacert_cert_build_start(
        &build_state,
        &g_cert_def,
        cert,
        &cert_size,
        g_ca_public_key);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);

    ret = atcacert_cert_build_finish(&build_state);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

TEST(atcacert_cert_build, finish_bad_params)
{
    int ret = 0;

    ret = atcacert_cert_build_finish(NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}


TEST_GROUP(atcacert_is_device_loc_overlap);

TEST_SETUP(atcacert_is_device_loc_overlap)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_is_device_loc_overlap)
{
}

// 0        10 15       25
// |---1---|
//             |---2---|
TEST(atcacert_is_device_loc_overlap, align1)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 10 - 0
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 15,
        .count      = 25 - 15
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(FALSE, ret);
}

// 0       10       20
// |---1---|
//         |---2---|
TEST(atcacert_is_device_loc_overlap, align2)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 10 - 0
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 20 - 10
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(FALSE, ret);
}

// 0      9 10     20
// |---1---|
//        |---2---|
TEST(atcacert_is_device_loc_overlap, align3)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 10 - 0
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 9,
        .count      = 20 - 9
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(TRUE, ret);
}

// 5  10       25 30
// |------1------|
//    |---2---|
TEST(atcacert_is_device_loc_overlap, align4)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 5,
        .count      = 30 - 5
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 25 - 10
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(TRUE, ret);
}

// 5  10       25 30
//    |---1---|
// |------2------|
TEST(atcacert_is_device_loc_overlap, align5)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 25 - 10
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 5,
        .count      = 30 - 5
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(TRUE, ret);
}

// 0      9 10     20
//        |---1---|
// |---2---|
TEST(atcacert_is_device_loc_overlap, align6)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 9,
        .count      = 20 - 9
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 10 - 0
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(TRUE, ret);
}

// 0       10       20
//         |---1---|
// |---2---|
TEST(atcacert_is_device_loc_overlap, align7)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 10 - 0
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 10,
        .count      = 20 - 10
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(FALSE, ret);
}

// 0        10 15       25
//             |---1---|
// |---2---|
TEST(atcacert_is_device_loc_overlap, align8)
{
    int ret = 0;
    static const atcacert_device_loc_t device_loc1 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 15,
        .count      = 25 - 15
    };
    static const atcacert_device_loc_t device_loc2 = {
        .zone       = DEVZONE_DATA,
        .slot       = 0,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 10 - 0
    };

    ret = atcacert_is_device_loc_overlap(&device_loc1, &device_loc2);
    TEST_ASSERT_EQUAL(FALSE, ret);
}


TEST_GROUP(atcacert_get_device_data);

TEST_SETUP(atcacert_get_device_data)
{
    useCert(&g_test_cert_def_1_signer);
}

TEST_TEAR_DOWN(atcacert_get_device_data)
{
}

TEST(atcacert_get_device_data, flow)
{
    int ret = 0;
    size_t i = 0;
    static const uint8_t cert[] = {
        0x30, 0x82, 0x01, 0xB1, 0x30, 0x82, 0x01, 0x57, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x40,
        0xC4, 0x8B, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x36,
        0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70,
        0x6C, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x19, 0x45, 0x78, 0x61,
        0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x52,
        0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x33, 0x30, 0x37,
        0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x34, 0x39, 0x30, 0x33, 0x30, 0x37, 0x31,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x3A, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
        0x0A, 0x0C, 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03,
        0x55, 0x04, 0x03, 0x0C, 0x1D, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x41, 0x54, 0x45,
        0x43, 0x43, 0x35, 0x30, 0x38, 0x41, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x20, 0x43, 0x34,
        0x38, 0x42, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06,
        0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x9F, 0x61, 0xEB,
        0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D,
        0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9, 0x20, 0x2D, 0x21,
        0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C,
        0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E, 0xA3, 0x50, 0x30,
        0x4E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
        0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x84, 0x93, 0xB4, 0xC8, 0x5C, 0x54,
        0x69, 0x0C, 0xEC, 0xA0, 0x42, 0x41, 0x0C, 0x90, 0xE9, 0x71, 0x98, 0x66, 0xDC, 0x48, 0x30, 0x1F,
        0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4F, 0xAA, 0x04, 0x1C, 0xBC,
        0x8D, 0xA5, 0xDF, 0xE2, 0x47, 0x72, 0x42, 0xBB, 0xB9, 0x5B, 0x51, 0x81, 0x19, 0x27, 0x6D, 0x30,
        0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
        0x02, 0x20, 0x63, 0xE6, 0xFD, 0xCC, 0x7A, 0x99, 0xD5, 0x0D, 0x6A, 0x06, 0x70, 0x2D, 0xC0, 0x2F,
        0x34, 0x25, 0x19, 0x2A, 0x10, 0x51, 0x99, 0xAE, 0x63, 0xFC, 0xEB, 0xD9, 0x33, 0xEB, 0x90, 0x25,
        0x7D, 0x2E, 0x02, 0x21, 0x00, 0xA9, 0x12, 0x89, 0xB5, 0xAE, 0x90, 0x02, 0x7C, 0xBC, 0xB1, 0xC7,
        0x44, 0x3A, 0x8A, 0x00, 0xBD, 0x15, 0xF2, 0xF5, 0x6F, 0x55, 0x01, 0xD1, 0x7A, 0xDF, 0xEF, 0x48,
        0x6B, 0x89, 0xF0, 0xC6, 0xAF
    };
    static const atcacert_device_loc_t device_loc_public_key = {
        .zone       = DEVZONE_DATA,
        .slot       = 11,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const atcacert_device_loc_t device_loc_comp_cert = {
        .zone       = DEVZONE_DATA,
        .slot       = 12,
        .is_genkey  = FALSE,
        .offset     = 0,
        .count      = 72
    };
    static const uint8_t comp_cert_ref[72] = {
        0x63, 0xe6, 0xfd, 0xcc, 0x7a, 0x99, 0xd5, 0x0d, 0x6a, 0x06, 0x70, 0x2d, 0xc0, 0x2f, 0x34, 0x25,
        0x19, 0x2a, 0x10, 0x51, 0x99, 0xae, 0x63, 0xfc, 0xeb, 0xd9, 0x33, 0xeb, 0x90, 0x25, 0x7d, 0x2e,
        0xa9, 0x12, 0x89, 0xb5, 0xae, 0x90, 0x02, 0x7c, 0xbc, 0xb1, 0xc7, 0x44, 0x3a, 0x8a, 0x00, 0xbd,
        0x15, 0xf2, 0xf5, 0x6f, 0x55, 0x01, 0xd1, 0x7a, 0xdf, 0xef, 0x48, 0x6b, 0x89, 0xf0, 0xc6, 0xaf,
        0xA9, 0x9D, 0x54, 0xC4, 0x8B, 0x10, 0x90, 0x00
    };
    atcacert_device_loc_t device_locs[4];
    size_t device_locs_count = 0;

    ret = atcacert_get_device_locs(
        &g_cert_def,
        device_locs,
        &device_locs_count,
        sizeof(device_locs) / sizeof(device_locs[0]),
        1);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(2, device_locs_count);

    for (i = 0; i < device_locs_count; i++)
    {
        uint8_t data[128];
        ret = atcacert_get_device_data(
            &g_cert_def,
            cert,
            sizeof(cert),
            &device_locs[i],
            data);
        TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
        if (device_locs[i].slot == device_loc_public_key.slot)
        {
            TEST_ASSERT_EQUAL(device_loc_public_key.offset, device_locs[i].offset);
            TEST_ASSERT_EQUAL(device_loc_public_key.count, device_locs[i].count);
            TEST_ASSERT_EQUAL_MEMORY(g_padded_public_key, data, device_locs[i].count);
        }
        else if (device_locs[i].slot == device_loc_comp_cert.slot)
        {
            TEST_ASSERT_EQUAL(device_loc_comp_cert.offset, device_locs[i].offset);
            TEST_ASSERT_EQUAL(device_loc_comp_cert.count, device_locs[i].count);
            TEST_ASSERT_EQUAL_MEMORY(comp_cert_ref, data, device_locs[i].count);
        }
        else
        {
            TEST_FAIL();
        }
    }
}


TEST_GROUP(atcacert_public_key_add_padding);

TEST_SETUP(atcacert_public_key_add_padding)
{
}

TEST_TEAR_DOWN(atcacert_public_key_add_padding)
{
}

TEST(atcacert_public_key_add_padding, separate)
{
    uint8_t padded_key[72];

    atcacert_public_key_add_padding(g_test_public_key, padded_key);
    TEST_ASSERT_EQUAL_MEMORY(g_padded_public_key, padded_key, sizeof(g_padded_public_key));
}

TEST(atcacert_public_key_add_padding, in_place)
{
    uint8_t key[72] = {
        0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2, 0x50, 0x29, 0x01, 0xEF,
        0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5, 0xFC, 0x53, 0xF1, 0xD9,
        0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5, 0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C,
        0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71, 0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    atcacert_public_key_add_padding(key, key);
    TEST_ASSERT_EQUAL_MEMORY(g_padded_public_key, key, sizeof(g_padded_public_key));
}


TEST_GROUP(atcacert_public_key_remove_padding);

TEST_SETUP(atcacert_public_key_remove_padding)
{
}

TEST_TEAR_DOWN(atcacert_public_key_remove_padding)
{
}

TEST(atcacert_public_key_remove_padding, separate)
{
    uint8_t raw_key[64];

    atcacert_public_key_remove_padding(g_padded_public_key, raw_key);
    TEST_ASSERT_EQUAL_MEMORY(g_test_public_key, raw_key, sizeof(g_test_public_key));
}

TEST(atcacert_public_key_remove_padding, in_place)
{
    uint8_t key[72] = {
        0x00, 0x00, 0x00, 0x00, 0x9F, 0x61, 0xEB, 0xA0, 0xD7, 0x9E, 0xF2, 0xC4, 0x96, 0xF1, 0x32, 0xF2,
        0x50, 0x29, 0x01, 0xEF, 0xD1, 0xE8, 0x6D, 0x45, 0x1A, 0xAC, 0x59, 0x70, 0xBE, 0x62, 0xF3, 0xE5,
        0xFC, 0x53, 0xF1, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2D, 0x21, 0x9B, 0x3B, 0x66, 0x53, 0xC5,
        0x5F, 0xD8, 0x1F, 0xAA, 0x99, 0x8C, 0x1F, 0x6C, 0x42, 0x14, 0x2C, 0x61, 0xB2, 0x83, 0x9E, 0x71,
        0x40, 0x06, 0xF2, 0x52, 0x7C, 0xFE, 0xA2, 0x3E
    };

    atcacert_public_key_remove_padding(key, key);
    TEST_ASSERT_EQUAL_MEMORY(g_test_public_key, key, sizeof(g_test_public_key));
}

TEST(atcacert_cert_build, max_cert_size_x509)
{
    int ret = 0;
    size_t max_cert_size = 0;

    useCert(&g_test_cert_def_0_device);
    ret = atcacert_max_cert_size(&g_cert_def, &max_cert_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.std_cert_elements[STDCERT_SIGNATURE].offset + 75, max_cert_size);
}

TEST(atcacert_cert_build, max_cert_size_x509_dynamic_sn)
{
    int ret = 0;
    size_t ref_max_cert_size;
    size_t max_cert_size = 0;

    useCert(&g_test_cert_def_0_device);
    g_cert_def.sn_source = SNSRC_STORED_DYNAMIC;
    g_cert_def.std_cert_elements[STDCERT_CERT_SN].offset -= 1;

    ref_max_cert_size = g_cert_def.std_cert_elements[STDCERT_SIGNATURE].offset + 75;
    ref_max_cert_size += 128 - g_cert_def.std_cert_elements[STDCERT_CERT_SN].count;

    ret = atcacert_max_cert_size(&g_cert_def, &max_cert_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(ref_max_cert_size, max_cert_size);
}

TEST(atcacert_cert_build, max_cert_size_x509_dynamic_sn_bad_size)
{
    int ret = 0;
    size_t max_cert_size = 0;

    useCert(&g_test_cert_def_0_device);
    g_cert_def.sn_source = SNSRC_STORED_DYNAMIC;
    ((uint8_t*)(g_cert_def.cert_template))[g_cert_def.std_cert_elements[STDCERT_CERT_SN].offset] = 128;
    ret = atcacert_max_cert_size(&g_cert_def, &max_cert_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_CERT, ret);
}

TEST(atcacert_cert_build, max_cert_size_custom)
{
    int ret = 0;
    size_t max_cert_size = 0;

    useCert(&g_test_cert_def_3_device);
    ret = atcacert_max_cert_size(&g_cert_def, &max_cert_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_SUCCESS, ret);
    TEST_ASSERT_EQUAL(g_cert_def.cert_template_size, max_cert_size);
}

TEST(atcacert_cert_build, max_cert_size_bad_params)
{
    int ret = 0;
    size_t max_cert_size = 0;

    useCert(&g_test_cert_def_3_device);

    ret = atcacert_max_cert_size(&g_cert_def, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_max_cert_size(NULL, &max_cert_size);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);

    ret = atcacert_max_cert_size(NULL, NULL);
    TEST_ASSERT_EQUAL(ATCACERT_E_BAD_PARAMS, ret);
}

#endif
